diff --git a/src/main/java/com/cultural/heritage/aop/AuthInterceptor.java b/src/main/java/com/cultural/heritage/aop/AuthInterceptor.java index 39d277b..4527f7f 100644 --- a/src/main/java/com/cultural/heritage/aop/AuthInterceptor.java +++ b/src/main/java/com/cultural/heritage/aop/AuthInterceptor.java @@ -37,7 +37,6 @@ public class AuthInterceptor { String mustRole = authCheck.mustRole(); RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); - //当前登录用户 User loginUser = userService.getLoginUser(request); //必须有该权限才通过 @@ -73,4 +72,5 @@ public class AuthInterceptor { //通过权限校验,放行 return joinPoint.proceed(); } + } diff --git a/src/main/java/com/cultural/heritage/controller/file/FileController.java b/src/main/java/com/cultural/heritage/controller/file/FileController.java index 380d614..9a422ab 100644 --- a/src/main/java/com/cultural/heritage/controller/file/FileController.java +++ b/src/main/java/com/cultural/heritage/controller/file/FileController.java @@ -16,12 +16,10 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; -import org.springframework.web.bind.annotation.PostMapping; -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.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.File; @@ -36,145 +34,145 @@ import java.util.Map; public class FileController { - @Resource - private UserService userService; + @Resource + private UserService userService; - @Resource - private IHweiYunOBSService iHweiYunOBSService; + @Resource + private IHweiYunOBSService iHweiYunOBSService; - /** - * 未登录的情况下的文件上传 - * @param multipartFile 文件上传参数 - * @param uploadFileRequest 文件业务类型请求体 - * @return 图片可访问地址 - */ - @PostMapping("/upload/server/not_login") - @Operation(summary = "(未使用)未登录情况下的文件上传", description = "参数:(文档上是false,但biz是必传的),文件对象(multipartFile), 业务类型(biz),权限:所有人,方法名:uploadServerFileNotLogin") - private BaseResponse uploadServerFileNotLogin(@RequestPart("file")MultipartFile multipartFile, UploadFileRequest uploadFileRequest) { - //获取业务名称 - String biz = uploadFileRequest.getBiz(); - FileUploadBizEnum fileUploadBizEnum = FileUploadBizEnum.getEnumByValue(biz); - if (fileUploadBizEnum == null) { - throw new BusinessException(ErrorCode.PARAMS_ERROR, "业务名称错误"); - } - // 校验文件 - validFile(multipartFile, fileUploadBizEnum); - //文件目录:根据业务、用户来划分 - String uuid = RandomStringUtils.randomAlphabetic(8); - String filename = uuid + "-" + multipartFile.getOriginalFilename(); - String filepath = String.format("/%s/%s/%s", fileUploadBizEnum.getValue(), 0, filename); + /** + * 未登录的情况下的文件上传 + * + * @param multipartFile 文件上传参数 + * @param uploadFileRequest 文件业务类型请求体 + * @return 图片可访问地址 + */ + @PostMapping("/upload/server/not_login") + @Operation(summary = "(未使用)未登录情况下的文件上传", description = "参数:(文档上是false,但biz是必传的),文件对象(multipartFile), 业务类型(biz),权限:所有人,方法名:uploadServerFileNotLogin") + private BaseResponse uploadServerFileNotLogin(@RequestPart("file") MultipartFile multipartFile, UploadFileRequest uploadFileRequest) { + // 获取业务名称 + String biz = uploadFileRequest.getBiz(); + FileUploadBizEnum fileUploadBizEnum = FileUploadBizEnum.getEnumByValue(biz); + if (fileUploadBizEnum == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "业务名称错误"); + } + // 校验文件 + validFile(multipartFile, fileUploadBizEnum); + // 文件目录:根据业务、用户来划分 + String uuid = RandomStringUtils.randomAlphabetic(8); + 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); - if (!file.exists()) { - // 创建目录 - boolean mkdirs = file.mkdirs(); - if (!mkdirs) { - throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建目录失败"); - } - } - //返回可访问地址 - String url = iHweiYunOBSService.fileUpload(multipartFile, "feiyi" + filepath); - return ResultUtils.success(url); - } + // 判断目录是否存在 + File file = new File(FileConstant.SERVER_UPLOAD_DIR, filepath); + if (!file.exists()) { + // 创建目录 + boolean mkdirs = file.mkdirs(); + if (!mkdirs) { + throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建目录失败"); + } + } + // 返回可访问地址 + String url = iHweiYunOBSService.fileUpload(multipartFile, "feiyi" + filepath); + return ResultUtils.success(url); + } - @PostMapping("/upload/server") - @Operation(summary = "已登录情况下的文件上传", description = "参数:(文档上是false,但biz是必传的),文件对象(multipartFile), 业务类型(biz),权限:所有人,方法名:uploadServerFile") - public BaseResponse uploadServerFile(@RequestPart("file")MultipartFile multipartFile, UploadFileRequest uploadFileRequest, HttpServletRequest request) { - //获取业务名称 - String biz = uploadFileRequest.getBiz(); - FileUploadBizEnum fileUploadBizEnum = FileUploadBizEnum.getEnumByValue(biz); - if (fileUploadBizEnum == null) { - throw new BusinessException(ErrorCode.PARAMS_ERROR, "业务名称错误"); - } - // 校验文件 - validFile(multipartFile, fileUploadBizEnum); - // 校验用户是否登录 - User loginUser = userService.getLoginUser(request); - if (loginUser == null) { - throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR, "未登录"); - } - // 文件目录:根据业务、用户来划分 - String uuid = RandomStringUtils.randomAlphabetic(8); - String filename = uuid + "-" + multipartFile.getOriginalFilename(); - String filepath = String.format("/%s/%s/%s", fileUploadBizEnum.getValue(), loginUser.getId(), filename); + @PostMapping("/upload/server") + @Operation(summary = "已登录情况下的文件上传", description = "参数:(文档上是false,但biz是必传的),文件对象(multipartFile), 业务类型(biz),权限:所有人,方法名:uploadServerFile") + public BaseResponse uploadServerFile(@RequestPart("file") MultipartFile multipartFile, UploadFileRequest uploadFileRequest, HttpServletRequest request) { + // 获取业务名称 + String biz = uploadFileRequest.getBiz(); + FileUploadBizEnum fileUploadBizEnum = FileUploadBizEnum.getEnumByValue(biz); + if (fileUploadBizEnum == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "业务名称错误"); + } + // 校验文件 + validFile(multipartFile, fileUploadBizEnum); + // 校验用户是否登录 + User loginUser = userService.getLoginUser(request); + if (loginUser == null) { + throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR, "未登录"); + } + // 文件目录:根据业务、用户来划分 + String uuid = RandomStringUtils.randomAlphabetic(8); + String filename = uuid + "-" + multipartFile.getOriginalFilename(); + String filepath = String.format("/%s/%s/%s", fileUploadBizEnum.getValue(), loginUser.getId(), filename); - // 判断目录是否存在 - File file = new File(FileConstant.SERVER_UPLOAD_DIR, filepath); - if (!file.exists()) { - // 创建目录 - boolean mkdirs = file.mkdirs(); - if (!mkdirs) { - throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建目录失败"); - } - } - //返回可访问地址 - String url = iHweiYunOBSService.fileUpload(multipartFile, "feiyi" + filepath); - return ResultUtils.success(url); - } + // 判断目录是否存在 + File file = new File(FileConstant.SERVER_UPLOAD_DIR, filepath); + if (!file.exists()) { + // 创建目录 + boolean mkdirs = file.mkdirs(); + if (!mkdirs) { + throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建目录失败"); + } + } + // 返回可访问地址 + String url = iHweiYunOBSService.fileUpload(multipartFile, "feiyi" + filepath); + return ResultUtils.success(url); + } - - @PostMapping("/upload/single") - @Operation(summary = "单独文件上传", description = "参数:file,文件对象(multipartFile),权限:所有人,方法名:uploadServerFile") - public Object uploadSingleServerFile(@RequestPart("file")MultipartFile multipartFile, HttpServletRequest request) { + @PostMapping("/upload/single") + @Operation(summary = "单独文件上传", description = "参数:file,文件对象(multipartFile),权限:所有人,方法名:uploadServerFile") + public Object uploadSingleServerFile(@RequestPart("file") MultipartFile multipartFile, HttpServletRequest request) { // - // 校验文件 - validFile(multipartFile, null); - // 文件目录:根据业务、用户来划分 - String uuid = RandomStringUtils.randomAlphabetic(8); - String filename = uuid + "-" + multipartFile.getOriginalFilename(); - String filepath = String.format("/%s/%s/%s", "single", "yt", filename); + // 校验文件 + validFile(multipartFile, null); + // 文件目录:根据业务、用户来划分 + String uuid = RandomStringUtils.randomAlphabetic(8); + String filename = uuid + "-" + multipartFile.getOriginalFilename(); + String filepath = String.format("/%s/%s/%s", "single", "yt", filename); - // 判断目录是否存在 - File file = new File(FileConstant.SERVER_UPLOAD_DIR, filepath); - if (!file.exists()) { - // 创建目录 - boolean mkdirs = file.mkdirs(); - if (!mkdirs) { - throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建目录失败"); - } - } - //返回可访问地址 - String url = iHweiYunOBSService.fileUpload(multipartFile, "feiyi" + filepath); + // 判断目录是否存在 + File file = new File(FileConstant.SERVER_UPLOAD_DIR, filepath); + if (!file.exists()) { + // 创建目录 + boolean mkdirs = file.mkdirs(); + if (!mkdirs) { + throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建目录失败"); + } + } + // 返回可访问地址 + String url = iHweiYunOBSService.fileUpload(multipartFile, "feiyi" + filepath); - Map data = new HashMap<>(); - data.put("url", url); + Map data = new HashMap<>(); + data.put("url", url); - // 创建最终的响应对象 - Map response = new HashMap<>(); - response.put("errno", 0); - response.put("data", data); - Gson gson = new Gson(); + // 创建最终的响应对象 + Map response = new HashMap<>(); + response.put("errno", 0); + response.put("data", data); + 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, "文件类型错误"); + } + } - - - - - /** - * 校验文件 - * - * @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); + } } diff --git a/src/main/java/com/cultural/heritage/exception/BusinessException.java b/src/main/java/com/cultural/heritage/exception/BusinessException.java index 7610f1c..c0839b6 100644 --- a/src/main/java/com/cultural/heritage/exception/BusinessException.java +++ b/src/main/java/com/cultural/heritage/exception/BusinessException.java @@ -32,4 +32,5 @@ public class BusinessException extends RuntimeException { public int getCode() { return code; } + } diff --git a/src/main/java/com/cultural/heritage/service/file/IHweiYunOBSService.java b/src/main/java/com/cultural/heritage/service/file/IHweiYunOBSService.java index f13014e..039d63f 100644 --- a/src/main/java/com/cultural/heritage/service/file/IHweiYunOBSService.java +++ b/src/main/java/com/cultural/heritage/service/file/IHweiYunOBSService.java @@ -1,5 +1,6 @@ package com.cultural.heritage.service.file; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.multipart.MultipartFile; /** @@ -7,30 +8,30 @@ import org.springframework.web.multipart.MultipartFile; */ public interface IHweiYunOBSService { - /** - * @Description 删除文件 - * @param: objectKey 文件名 - * @return: boolean 执行结果 - */ + /** + * @Description 删除文件 + * @param: objectKey 文件名 + * @return: boolean 执行结果 + */ // boolean delete(String objectKey); // boolean deleteFileByPath(String objectKey); - /** - * @Description 批量删除文件 - * @param: objectKeys 文件名集合 - * @return: boolean 执行结果 - */ + /** + * @Description 批量删除文件 + * @param: objectKeys 文件名集合 + * @return: boolean 执行结果 + */ // boolean delete(List objectKeys); - /** - * @Description 上传文件 - * @param: uploadFile 上传文件 - * @param: objectKey 文件名称 - * @return: java.lang.String url访问路径 - */ - String fileUpload(MultipartFile uploadFile, String objectKey); + /** + * @Description 上传文件 + * @param: uploadFile 上传文件 + * @param: objectKey 文件名称 + * @return: java.lang.String url访问路径 + */ + String fileUpload(MultipartFile uploadFile, String objectKey); -// String uploadFileByte(byte data[], String objectKey); + // String uploadFileByte(byte data[], String objectKey); // String uploadFile(File file); // // /** @@ -39,4 +40,6 @@ public interface IHweiYunOBSService { // * @return: java.io.InputStream // */ // InputStream fileDownload(String objectKey); + void downloadFile(String objectKey, HttpServletResponse response); + } diff --git a/src/main/java/com/cultural/heritage/service/file/impl/HweiYunOBSServiceImpl.java b/src/main/java/com/cultural/heritage/service/file/impl/HweiYunOBSServiceImpl.java index 9508fe2..79d806f 100644 --- a/src/main/java/com/cultural/heritage/service/file/impl/HweiYunOBSServiceImpl.java +++ b/src/main/java/com/cultural/heritage/service/file/impl/HweiYunOBSServiceImpl.java @@ -5,6 +5,8 @@ import com.cultural.heritage.service.file.IHweiYunOBSService; import com.obs.services.ObsClient; import com.obs.services.exception.ObsException; import com.obs.services.model.*; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -12,6 +14,8 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; 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 { - @Autowired - private HweiOBSConfig hweiOBSConfig; + @Autowired + private HweiOBSConfig hweiOBSConfig; // @Override // public boolean delete(String objectKey) { @@ -84,37 +88,73 @@ public class HweiYunOBSServiceImpl implements IHweiYunOBSService { // return false; // } - @Override - public String fileUpload(MultipartFile uploadFile, String objectKey) { - ObsClient obsClient = null; - try { - String bucketName = hweiOBSConfig.getBucketName(); - obsClient = hweiOBSConfig.getInstance(); - // 判断桶是否存在 - boolean exists = obsClient.headBucket(bucketName); - if (!exists) { - // 若不存在,则创建桶 - HeaderResponse response = obsClient.createBucket(bucketName); - } - InputStream inputStream = uploadFile.getInputStream(); - long available = inputStream.available(); - PutObjectRequest request = new PutObjectRequest(bucketName, objectKey, inputStream); + @Override + public String fileUpload(MultipartFile uploadFile, String objectKey) { + ObsClient obsClient = null; + try { + String bucketName = hweiOBSConfig.getBucketName(); + obsClient = hweiOBSConfig.getInstance(); + // 判断桶是否存在 + boolean exists = obsClient.headBucket(bucketName); + if (!exists) { + // 若不存在,则创建桶 + HeaderResponse response = obsClient.createBucket(bucketName); + } + InputStream inputStream = uploadFile.getInputStream(); + long available = inputStream.available(); + PutObjectRequest request = new PutObjectRequest(bucketName, objectKey, inputStream); - ObjectMetadata objectMetadata = new ObjectMetadata(); - objectMetadata.setContentLength(available); - request.setMetadata(objectMetadata); - // 设置对象访问权限为公共读 - request.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ); - PutObjectResult result = obsClient.putObject(request); - // 读取该已上传对象的URL - return result.getObjectUrl(); - } catch (ObsException e) { - } catch (IOException e) { - } finally { - hweiOBSConfig.destroy(obsClient); - } - return null; - } + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentLength(available); + request.setMetadata(objectMetadata); + // 设置对象访问权限为公共读 + request.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ); + PutObjectResult result = obsClient.putObject(request); + // 读取该已上传对象的URL + return result.getObjectUrl(); + } catch (ObsException | IOException e) { + } finally { + hweiOBSConfig.destroy(obsClient); + } + 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 // public String uploadFileByte(byte[] data, String fileName) {