增加通过objectKey下载OBS文件

This commit is contained in:
yuanbaolei 2025-03-15 17:57:23 +08:00
parent 6cdaf6c1ef
commit fcd668e590
5 changed files with 221 additions and 179 deletions

View File

@ -37,7 +37,6 @@ public class AuthInterceptor {
String mustRole = authCheck.mustRole(); String mustRole = authCheck.mustRole();
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
//当前登录用户 //当前登录用户
User loginUser = userService.getLoginUser(request); User loginUser = userService.getLoginUser(request);
//必须有该权限才通过 //必须有该权限才通过
@ -73,4 +72,5 @@ public class AuthInterceptor {
//通过权限校验放行 //通过权限校验放行
return joinPoint.proceed(); return joinPoint.proceed();
} }
} }

View File

@ -16,12 +16,10 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.File; import java.io.File;
@ -36,145 +34,145 @@ import java.util.Map;
public class FileController { public class FileController {
@Resource @Resource
private UserService userService; private UserService userService;
@Resource @Resource
private IHweiYunOBSService iHweiYunOBSService; private IHweiYunOBSService iHweiYunOBSService;
/** /**
* 未登录的情况下的文件上传 * 未登录的情况下的文件上传
* @param multipartFile 文件上传参数 *
* @param uploadFileRequest 文件业务类型请求体 * @param multipartFile 文件上传参数
* @return 图片可访问地址 * @param uploadFileRequest 文件业务类型请求体
*/ * @return 图片可访问地址
@PostMapping("/upload/server/not_login") */
@Operation(summary = "(未使用)未登录情况下的文件上传", description = "参数:(文档上是false但biz是必传的)文件对象multipartFile), 业务类型(biz)权限所有人方法名uploadServerFileNotLogin") @PostMapping("/upload/server/not_login")
private BaseResponse<String> uploadServerFileNotLogin(@RequestPart("file")MultipartFile multipartFile, UploadFileRequest uploadFileRequest) { @Operation(summary = "(未使用)未登录情况下的文件上传", description = "参数:(文档上是false但biz是必传的)文件对象multipartFile), 业务类型(biz)权限所有人方法名uploadServerFileNotLogin")
//获取业务名称 private BaseResponse<String> uploadServerFileNotLogin(@RequestPart("file") MultipartFile multipartFile, UploadFileRequest uploadFileRequest) {
String biz = uploadFileRequest.getBiz(); // 获取业务名称
FileUploadBizEnum fileUploadBizEnum = FileUploadBizEnum.getEnumByValue(biz); String biz = uploadFileRequest.getBiz();
if (fileUploadBizEnum == null) { FileUploadBizEnum fileUploadBizEnum = FileUploadBizEnum.getEnumByValue(biz);
throw new BusinessException(ErrorCode.PARAMS_ERROR, "业务名称错误"); if (fileUploadBizEnum == null) {
} throw new BusinessException(ErrorCode.PARAMS_ERROR, "业务名称错误");
// 校验文件 }
validFile(multipartFile, fileUploadBizEnum); // 校验文件
//文件目录根据业务用户来划分 validFile(multipartFile, fileUploadBizEnum);
String uuid = RandomStringUtils.randomAlphabetic(8); // 文件目录根据业务用户来划分
String filename = uuid + "-" + multipartFile.getOriginalFilename(); String uuid = RandomStringUtils.randomAlphabetic(8);
String filepath = String.format("/%s/%s/%s", fileUploadBizEnum.getValue(), 0, filename); String filename = uuid + "-" + multipartFile.getOriginalFilename();
String filepath = String.format("/%s/%s/%s", fileUploadBizEnum.getValue(), 0, filename);
// 判断目录是否存在 // 判断目录是否存在
File file = new File(FileConstant.SERVER_UPLOAD_DIR, filepath); File file = new File(FileConstant.SERVER_UPLOAD_DIR, filepath);
if (!file.exists()) { if (!file.exists()) {
// 创建目录 // 创建目录
boolean mkdirs = file.mkdirs(); boolean mkdirs = file.mkdirs();
if (!mkdirs) { if (!mkdirs) {
throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建目录失败"); throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建目录失败");
} }
} }
//返回可访问地址 // 返回可访问地址
String url = iHweiYunOBSService.fileUpload(multipartFile, "feiyi" + filepath); String url = iHweiYunOBSService.fileUpload(multipartFile, "feiyi" + filepath);
return ResultUtils.success(url); return ResultUtils.success(url);
} }
@PostMapping("/upload/server") @PostMapping("/upload/server")
@Operation(summary = "已登录情况下的文件上传", description = "参数:(文档上是false但biz是必传的)文件对象multipartFile), 业务类型(biz)权限所有人方法名uploadServerFile") @Operation(summary = "已登录情况下的文件上传", description = "参数:(文档上是false但biz是必传的)文件对象multipartFile), 业务类型(biz)权限所有人方法名uploadServerFile")
public BaseResponse<String> uploadServerFile(@RequestPart("file")MultipartFile multipartFile, UploadFileRequest uploadFileRequest, HttpServletRequest request) { public BaseResponse<String> uploadServerFile(@RequestPart("file") MultipartFile multipartFile, UploadFileRequest uploadFileRequest, HttpServletRequest request) {
//获取业务名称 // 获取业务名称
String biz = uploadFileRequest.getBiz(); String biz = uploadFileRequest.getBiz();
FileUploadBizEnum fileUploadBizEnum = FileUploadBizEnum.getEnumByValue(biz); FileUploadBizEnum fileUploadBizEnum = FileUploadBizEnum.getEnumByValue(biz);
if (fileUploadBizEnum == null) { if (fileUploadBizEnum == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "业务名称错误"); throw new BusinessException(ErrorCode.PARAMS_ERROR, "业务名称错误");
} }
// 校验文件 // 校验文件
validFile(multipartFile, fileUploadBizEnum); validFile(multipartFile, fileUploadBizEnum);
// 校验用户是否登录 // 校验用户是否登录
User loginUser = userService.getLoginUser(request); User loginUser = userService.getLoginUser(request);
if (loginUser == null) { if (loginUser == null) {
throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR, "未登录"); throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR, "未登录");
} }
// 文件目录根据业务用户来划分 // 文件目录根据业务用户来划分
String uuid = RandomStringUtils.randomAlphabetic(8); String uuid = RandomStringUtils.randomAlphabetic(8);
String filename = uuid + "-" + multipartFile.getOriginalFilename(); String filename = uuid + "-" + multipartFile.getOriginalFilename();
String filepath = String.format("/%s/%s/%s", fileUploadBizEnum.getValue(), loginUser.getId(), filename); String filepath = String.format("/%s/%s/%s", fileUploadBizEnum.getValue(), loginUser.getId(), filename);
// 判断目录是否存在 // 判断目录是否存在
File file = new File(FileConstant.SERVER_UPLOAD_DIR, filepath); File file = new File(FileConstant.SERVER_UPLOAD_DIR, filepath);
if (!file.exists()) { if (!file.exists()) {
// 创建目录 // 创建目录
boolean mkdirs = file.mkdirs(); boolean mkdirs = file.mkdirs();
if (!mkdirs) { if (!mkdirs) {
throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建目录失败"); throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建目录失败");
} }
} }
//返回可访问地址 // 返回可访问地址
String url = iHweiYunOBSService.fileUpload(multipartFile, "feiyi" + filepath); String url = iHweiYunOBSService.fileUpload(multipartFile, "feiyi" + filepath);
return ResultUtils.success(url); return ResultUtils.success(url);
} }
@PostMapping("/upload/single")
@PostMapping("/upload/single") @Operation(summary = "单独文件上传", description = "参数file文件对象multipartFile)权限所有人方法名uploadServerFile")
@Operation(summary = "单独文件上传", description = "参数file文件对象multipartFile)权限所有人方法名uploadServerFile") public Object uploadSingleServerFile(@RequestPart("file") MultipartFile multipartFile, HttpServletRequest request) {
public Object uploadSingleServerFile(@RequestPart("file")MultipartFile multipartFile, HttpServletRequest request) {
// //
// 校验文件 // 校验文件
validFile(multipartFile, null); validFile(multipartFile, null);
// 文件目录根据业务用户来划分 // 文件目录根据业务用户来划分
String uuid = RandomStringUtils.randomAlphabetic(8); String uuid = RandomStringUtils.randomAlphabetic(8);
String filename = uuid + "-" + multipartFile.getOriginalFilename(); String filename = uuid + "-" + multipartFile.getOriginalFilename();
String filepath = String.format("/%s/%s/%s", "single", "yt", filename); String filepath = String.format("/%s/%s/%s", "single", "yt", filename);
// 判断目录是否存在 // 判断目录是否存在
File file = new File(FileConstant.SERVER_UPLOAD_DIR, filepath); File file = new File(FileConstant.SERVER_UPLOAD_DIR, filepath);
if (!file.exists()) { if (!file.exists()) {
// 创建目录 // 创建目录
boolean mkdirs = file.mkdirs(); boolean mkdirs = file.mkdirs();
if (!mkdirs) { if (!mkdirs) {
throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建目录失败"); throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建目录失败");
} }
} }
//返回可访问地址 // 返回可访问地址
String url = iHweiYunOBSService.fileUpload(multipartFile, "feiyi" + filepath); String url = iHweiYunOBSService.fileUpload(multipartFile, "feiyi" + filepath);
Map<String, String> data = new HashMap<>(); Map<String, String> data = new HashMap<>();
data.put("url", url); data.put("url", url);
// 创建最终的响应对象 // 创建最终的响应对象
Map<String, Object> response = new HashMap<>(); Map<String, Object> response = new HashMap<>();
response.put("errno", 0); response.put("errno", 0);
response.put("data", data); response.put("data", data);
Gson gson = new Gson(); Gson gson = new Gson();
return gson.fromJson(gson.toJson(response), Object.class);
}
return gson.fromJson(gson.toJson(response), Object.class); /**
} * 校验文件
*
* @param multipartFile 文件
* @param fileUploadBizEnum 业务类型
*/
private void validFile(MultipartFile multipartFile, FileUploadBizEnum fileUploadBizEnum) {
// 文件大小
long fileSize = multipartFile.getSize();
// 文件后缀
String fileSuffix = FileUtil.getSuffix(multipartFile.getOriginalFilename());
final long LIMIT = 30 * 1024 * 1024L;
if (fileSize > LIMIT) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件大小不能超过30MB");
}
if (!Arrays.asList("jpeg", "jpg", "svg", "png", "webp", "JPG").contains(fileSuffix)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件类型错误");
}
}
@GetMapping("downloadFile")
public void downloadFile(@RequestParam String objectKey, HttpServletResponse response) {
iHweiYunOBSService.downloadFile(objectKey, response);
}
/**
* 校验文件
*
* @param multipartFile 文件
* @param fileUploadBizEnum 业务类型
*/
private void validFile(MultipartFile multipartFile, FileUploadBizEnum fileUploadBizEnum) {
//文件大小
long fileSize = multipartFile.getSize();
//文件后缀
String fileSuffix = FileUtil.getSuffix(multipartFile.getOriginalFilename());
final long LIMIT = 30 * 1024 * 1024L;
if (fileSize > LIMIT) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件大小不能超过30MB");
}
if (!Arrays.asList("jpeg", "jpg", "svg", "png", "webp", "JPG").contains(fileSuffix)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件类型错误");
}
}
} }

View File

@ -32,4 +32,5 @@ public class BusinessException extends RuntimeException {
public int getCode() { public int getCode() {
return code; return code;
} }
} }

View File

@ -1,5 +1,6 @@
package com.cultural.heritage.service.file; package com.cultural.heritage.service.file;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
/** /**
@ -7,30 +8,30 @@ import org.springframework.web.multipart.MultipartFile;
*/ */
public interface IHweiYunOBSService { public interface IHweiYunOBSService {
/** /**
* @Description 删除文件 * @Description 删除文件
* @param: objectKey 文件名 * @param: objectKey 文件名
* @return: boolean 执行结果 * @return: boolean 执行结果
*/ */
// boolean delete(String objectKey); // boolean delete(String objectKey);
// boolean deleteFileByPath(String objectKey); // boolean deleteFileByPath(String objectKey);
/** /**
* @Description 批量删除文件 * @Description 批量删除文件
* @param: objectKeys 文件名集合 * @param: objectKeys 文件名集合
* @return: boolean 执行结果 * @return: boolean 执行结果
*/ */
// boolean delete(List<String> objectKeys); // boolean delete(List<String> objectKeys);
/** /**
* @Description 上传文件 * @Description 上传文件
* @param: uploadFile 上传文件 * @param: uploadFile 上传文件
* @param: objectKey 文件名称 * @param: objectKey 文件名称
* @return: java.lang.String url访问路径 * @return: java.lang.String url访问路径
*/ */
String fileUpload(MultipartFile uploadFile, String objectKey); String fileUpload(MultipartFile uploadFile, String objectKey);
// String uploadFileByte(byte data[], String objectKey); // String uploadFileByte(byte data[], String objectKey);
// String uploadFile(File file); // String uploadFile(File file);
// //
// /** // /**
@ -39,4 +40,6 @@ public interface IHweiYunOBSService {
// * @return: java.io.InputStream // * @return: java.io.InputStream
// */ // */
// InputStream fileDownload(String objectKey); // InputStream fileDownload(String objectKey);
void downloadFile(String objectKey, HttpServletResponse response);
} }

View File

@ -5,6 +5,8 @@ import com.cultural.heritage.service.file.IHweiYunOBSService;
import com.obs.services.ObsClient; import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException; import com.obs.services.exception.ObsException;
import com.obs.services.model.*; import com.obs.services.model.*;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -12,6 +14,8 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/** /**
@ -23,8 +27,8 @@ import java.io.InputStream;
public class HweiYunOBSServiceImpl implements IHweiYunOBSService { public class HweiYunOBSServiceImpl implements IHweiYunOBSService {
@Autowired @Autowired
private HweiOBSConfig hweiOBSConfig; private HweiOBSConfig hweiOBSConfig;
// @Override // @Override
// public boolean delete(String objectKey) { // public boolean delete(String objectKey) {
@ -84,37 +88,73 @@ public class HweiYunOBSServiceImpl implements IHweiYunOBSService {
// return false; // return false;
// } // }
@Override @Override
public String fileUpload(MultipartFile uploadFile, String objectKey) { public String fileUpload(MultipartFile uploadFile, String objectKey) {
ObsClient obsClient = null; ObsClient obsClient = null;
try { try {
String bucketName = hweiOBSConfig.getBucketName(); String bucketName = hweiOBSConfig.getBucketName();
obsClient = hweiOBSConfig.getInstance(); obsClient = hweiOBSConfig.getInstance();
// 判断桶是否存在 // 判断桶是否存在
boolean exists = obsClient.headBucket(bucketName); boolean exists = obsClient.headBucket(bucketName);
if (!exists) { if (!exists) {
// 若不存在则创建桶 // 若不存在则创建桶
HeaderResponse response = obsClient.createBucket(bucketName); HeaderResponse response = obsClient.createBucket(bucketName);
} }
InputStream inputStream = uploadFile.getInputStream(); InputStream inputStream = uploadFile.getInputStream();
long available = inputStream.available(); long available = inputStream.available();
PutObjectRequest request = new PutObjectRequest(bucketName, objectKey, inputStream); PutObjectRequest request = new PutObjectRequest(bucketName, objectKey, inputStream);
ObjectMetadata objectMetadata = new ObjectMetadata(); ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(available); objectMetadata.setContentLength(available);
request.setMetadata(objectMetadata); request.setMetadata(objectMetadata);
// 设置对象访问权限为公共读 // 设置对象访问权限为公共读
request.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ); request.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
PutObjectResult result = obsClient.putObject(request); PutObjectResult result = obsClient.putObject(request);
// 读取该已上传对象的URL // 读取该已上传对象的URL
return result.getObjectUrl(); return result.getObjectUrl();
} catch (ObsException e) { } catch (ObsException | IOException e) {
} catch (IOException e) { } finally {
} finally { hweiOBSConfig.destroy(obsClient);
hweiOBSConfig.destroy(obsClient); }
} return null;
return null; }
}
/*
* @Description : 文件下载
* @author : YBL
* @date : 2025/3/14 14:46
*/
@Override
public void downloadFile(String objectKey, HttpServletResponse response) {
// 使用永久AK/SK初始化客户端
ObsClient obsClient = hweiOBSConfig.getInstance();
try {
// 清空response
response.reset();
// 设置response的Header
response.setContentType("application/octet-stream");
response.addHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(objectKey, StandardCharsets.UTF_8));
response.setCharacterEncoding("UTF-8");
// 流式下载
ObsObject obsObject = obsClient.getObject(hweiOBSConfig.getBucketName(), objectKey);
// 读取对象内容
System.out.println("Object content:");
InputStream inputStream = obsObject.getObjectContent();
byte[] b = new byte[1024];
ServletOutputStream outputStream = response.getOutputStream();
int len;
while ((len = inputStream.read(b)) != -1) {
outputStream.write(b, 0, len);
}
System.out.println("getObjectContent successfully");
outputStream.close();
inputStream.close();
} catch (Exception e) {
System.out.println("getObjectContent failed");
// 其他异常信息打印
e.printStackTrace();
}
}
// @Override // @Override
// public String uploadFileByte(byte[] data, String fileName) { // public String uploadFileByte(byte[] data, String fileName) {