diff --git a/bonus-modules/bonus-mongodb/pom.xml b/bonus-modules/bonus-mongodb/pom.xml index 6eed84e..56987fd 100644 --- a/bonus-modules/bonus-mongodb/pom.xml +++ b/bonus-modules/bonus-mongodb/pom.xml @@ -9,7 +9,6 @@ 3.6.4 - com.bonus.mongoDB bonus-modules-mongodb diff --git a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/controller/ObsController.java b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/controller/ObsController.java index 10cafc3..d0b9d8a 100644 --- a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/controller/ObsController.java +++ b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/controller/ObsController.java @@ -1,8 +1,8 @@ package com.bonus.obs.controller; import com.bonus.common.core.domain.R; +import com.bonus.common.core.utils.file.FileUtils; import com.bonus.obs.service.ObsService; -import com.bonus.obs.utils.FileUtils; import com.obs.services.model.DeleteObjectResult; import com.obs.services.model.ObsObject; import com.obs.services.model.PutObjectResult; diff --git a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/ObsService.java b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/ObsService.java index c9c64ce..027805a 100644 --- a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/ObsService.java +++ b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/ObsService.java @@ -10,10 +10,10 @@ public interface ObsService { /** * 文件上传 * - * @param param 文件流 + * @param file 文件流 * @return 文件信息 */ - R uploadFile(MultipartFile param); + R uploadFile(MultipartFile file); /** * 删除文件从OBS @@ -28,4 +28,13 @@ public interface ObsService { * @param objectKey 文件在OBS中的键 */ public R downloadFile(String objectKey); + + + /** + * 文件上传 + * + * @param files 文件流 + * @return 文件信息 + */ + R uploadFiles(MultipartFile[] files); } diff --git a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/impl/ObsServiceImpl.java b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/impl/ObsServiceImpl.java index 8042338..16de3af 100644 --- a/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/impl/ObsServiceImpl.java +++ b/bonus-modules/bonus-obs/src/main/java/com/bonus/obs/service/impl/ObsServiceImpl.java @@ -1,8 +1,8 @@ package com.bonus.obs.service.impl; import com.bonus.common.core.domain.R; +import com.bonus.common.core.utils.file.FileUtils; import com.bonus.obs.service.ObsService; -import com.bonus.obs.utils.FileUtils; import com.bonus.obs.utils.ObsUtils; import com.obs.services.model.DeleteObjectResult; import com.obs.services.model.ObsObject; @@ -21,16 +21,15 @@ public class ObsServiceImpl implements ObsService { /** * 文件上传 * - * @param param 文件流 + * @param file 文件流 * @return 文件信息 */ @Override - public R uploadFile(MultipartFile param) { + public R uploadFile(MultipartFile file) { try { - String objectKey = param.getOriginalFilename(); - File file = FileUtils.multipartFileToFile(param); + String objectKey = file.getOriginalFilename(); objectKey = FileUtils.generateObjectName(objectKey); - return obsUtils.uploadFile(objectKey, file); + return obsUtils.uploadFile(objectKey, FileUtils.multipartFileToFile(file)); } catch (Exception e) { return R.fail(e.getMessage()); } @@ -55,4 +54,15 @@ public class ObsServiceImpl implements ObsService { public R downloadFile(String objectKey) { return obsUtils.downloadFile(objectKey); } + + /** + * 文件上传 + * + * @param files 文件流 + * @return 文件信息 + */ + @Override + public R uploadFiles(MultipartFile[] files) { + return null; + } } diff --git a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/config/OSSConfig.java b/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/config/OSSConfig.java index 5d0ac07..b530607 100644 --- a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/config/OSSConfig.java +++ b/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/config/OSSConfig.java @@ -1,47 +1,40 @@ package com.bonus.oss.config; +import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; +/** + * 配置OSS(对象存储服务)的属性类。 + * 使用@ConfigurationProperties注解将类绑定到配置文件中以oss为前缀的属性上。 + * 使用@Configuration注解将此类标记为一个配置类,它会被Spring Boot自动检测并用于配置上下文。 + * 使用@Data注解来自动生成getter和setter方法,简化了属性访问。 + */ @Configuration @ConfigurationProperties(prefix = "oss") +@Data public class OSSConfig { + /** + * OSS的访问密钥ID。 + * 用于身份验证的重要凭证之一。 + */ private String accessKeyId; + + /** + * OSS的访问密钥秘钥。 + * 用于身份验证的重要凭证之一,应保密。 + */ private String accessKeySecret; + + /** + * OSS的存储桶名称。 + * 存储桶是OSS中用于存储对象的容器。 + */ private String bucket; + + /** + * OSS的Endpoint。 + * Endpoint指定了与OSS交互时使用的域名或区域。 + */ private String endpoint; - // Getters and Setters - - public String getAccessKeyId() { - return accessKeyId; - } - - public void setAccessKeyId(String accessKeyId) { - this.accessKeyId = accessKeyId; - } - - public String getAccessKeySecret() { - return accessKeySecret; - } - - public void setAccessKeySecret(String accessKeySecret) { - this.accessKeySecret = accessKeySecret; - } - - public String getBucket() { - return bucket; - } - - public void setBucket(String bucket) { - this.bucket = bucket; - } - - public String getEndpoint() { - return endpoint; - } - - public void setEndpoint(String endpoint) { - this.endpoint = endpoint; - } - } diff --git a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/controller/OssController.java b/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/controller/OssController.java index 7a7e552..2642877 100644 --- a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/controller/OssController.java +++ b/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/controller/OssController.java @@ -2,9 +2,11 @@ package com.bonus.oss.controller; import com.aliyun.oss.model.OSSObject; import com.bonus.common.core.domain.R; +import com.bonus.common.core.utils.StringUtils; import com.bonus.common.core.utils.file.FileUtils; import com.bonus.oss.domain.OssInfo; import com.bonus.oss.service.OssService; +import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.formula.functions.T; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -13,15 +15,16 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.List; +@Slf4j @RestController @RequestMapping("/oss") public class OssController { @@ -34,9 +37,9 @@ public class OssController { * @param file 文件流 * @return 文件信息 */ - @PostMapping("/upload") - public R upload(MultipartFile file) { - return ossService.upload(file); + @PostMapping("/uploadFile") + public R uploadFile(MultipartFile file) { + return ossService.uploadFile(file); } @@ -54,33 +57,43 @@ public class OssController { /** * 文件下载 * - * @param ossFilePath oss文件存储地址 + * @param objectKey oss文件存储地址 */ - @GetMapping("/download") - public void download(HttpServletRequest request, HttpServletResponse response, @RequestParam String ossFilePath) { - try (OSSObject ossObject = ossService.download(ossFilePath)) { - if (ossObject == null) { - response.setStatus(HttpStatus.NOT_FOUND.value()); - return; - } - InputStream inputStream = ossObject.getObjectContent(); - String safeFileName = FileUtils.getFileNameFromPath(ossFilePath); - String encodedFileName = URLEncoder.encode(safeFileName, StandardCharsets.UTF_8.toString()); - response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); - response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\""); - try (OutputStream outputStream = response.getOutputStream()) { - byte[] buffer = new byte[8192]; - int bytesRead; - while ((bytesRead = inputStream.read(buffer)) != -1) { - outputStream.write(buffer, 0, bytesRead); - } - outputStream.flush(); - } catch (IOException e) { - response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); + @GetMapping("/downloadFile") + public void downloadFile(HttpServletResponse response, @RequestParam String objectKey) throws UnsupportedEncodingException { + R ossObjectR = ossService.downloadFile(objectKey); + if (ossObjectR.getData() == null) { + response.setStatus(HttpStatus.NOT_FOUND.value()); + return; + } + + OSSObject ossObject = ossObjectR.getData(); + String safeFileName = FileUtils.getName(objectKey); // 假设这个方法进行了恰当的文件名清理和验证 + if (!StringUtils.hasText(safeFileName)) { + response.setStatus(HttpStatus.BAD_REQUEST.value()); + return; + } + + String encodedFileName = URLEncoder.encode(safeFileName, StandardCharsets.UTF_8.toString()); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\""); + + try (InputStream inputStream = ossObject.getObjectContent(); + OutputStream outputStream = response.getOutputStream()) { + + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); } + outputStream.flush(); + } catch (IOException e) { + response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); } catch (IllegalArgumentException e) { response.setStatus(HttpStatus.BAD_REQUEST.value()); } catch (Exception e) { + // 记录异常信息到日志 + log.error("文件下载过程中出现未知异常,原因是:", e); response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); } } @@ -89,11 +102,11 @@ public class OssController { /** * 文件删除 * - * @param ossFilePath 文件路径 + * @param objectKey 文件路径 * @return 删除结果 */ - @PostMapping("/delete") - public R delete(@RequestParam String ossFilePath) { - return ossService.delete(ossFilePath); + @PostMapping("/deleteFile") + public R deleteFile(@RequestParam String objectKey) { + return ossService.deleteFile(objectKey); } } diff --git a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/domain/OssInfo.java b/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/domain/OssInfo.java index e91c430..a106f60 100644 --- a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/domain/OssInfo.java +++ b/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/domain/OssInfo.java @@ -1,9 +1,7 @@ package com.bonus.oss.domain; -import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; -import lombok.NoArgsConstructor; /** * OssInfo类用于封装OSS(Object Storage Service)对象的相关信息。 @@ -41,4 +39,5 @@ public class OssInfo { * Bucket是OSS中用于存储对象的容器,每个对象必须属于某个Bucket。 */ private String bucketName; + } diff --git a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/service/OssService.java b/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/service/OssService.java index 98ae794..5a7e0e8 100644 --- a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/service/OssService.java +++ b/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/service/OssService.java @@ -16,23 +16,23 @@ public interface OssService { * @param param 文件流 * @return 文件信息 */ - R upload(MultipartFile param); + R uploadFile(MultipartFile param); /** * 文件下载 * - * @param ossFilePath oss文件存储地址 + * @param objectKey oss文件存储地址 * @return OSSObject对象 */ - OSSObject download(String ossFilePath); + R downloadFile(String objectKey); /** * 文件删除 * - * @param ossFilePath oss文件存储地址 + * @param objectKey oss文件存储地址 * @return 操作结果 */ - R delete(String ossFilePath); + R deleteFile(String objectKey); /** * 多文件上传 * diff --git a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/service/impl/OssServiceImpl.java b/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/service/impl/OssServiceImpl.java index b529f4e..e28b04e 100644 --- a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/service/impl/OssServiceImpl.java +++ b/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/service/impl/OssServiceImpl.java @@ -1,7 +1,9 @@ package com.bonus.oss.service.impl; +import com.alibaba.nacos.common.utils.UuidUtils; import com.aliyun.oss.model.OSSObject; import com.bonus.common.core.domain.R; +import com.bonus.common.core.utils.StringUtils; import com.bonus.common.core.utils.file.FileUtils; import com.bonus.oss.domain.OssInfo; import com.bonus.oss.service.OssService; @@ -15,6 +17,9 @@ import javax.annotation.Resource; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; @Service public class OssServiceImpl implements OssService { @@ -22,19 +27,25 @@ public class OssServiceImpl implements OssService { @Resource private OssUtils ossUtils; + private ExecutorService executor = Executors.newFixedThreadPool(5); // 限制并发线程数为5 + /** * 文件上传 * - * @param multipartFile 文件流 + * @param file 文件流 * @return 文件信息 */ @Override - public R upload(MultipartFile multipartFile) { + public R uploadFile(MultipartFile file) { + if (ObjectUtils.isEmpty(file)) { + return R.fail("File is null."); + } try { - String objectKey = multipartFile.getOriginalFilename(); - File file = FileUtils.multipartFileToFile(multipartFile); + String originalFilename = Objects.requireNonNull(file.getOriginalFilename(), "文件名不能为空"); + String extension = originalFilename.substring(originalFilename.lastIndexOf('.')); + String objectKey = UuidUtils.generateUuid() + extension; objectKey = FileUtils.generateObjectName(objectKey); - return ossUtils.upload(objectKey, file); + return ossUtils.upload(objectKey, FileUtils.multipartFileToFile(file)); } catch (Exception e) { return R.fail("File upload failed."); } @@ -43,25 +54,28 @@ public class OssServiceImpl implements OssService { /** * 文件下载 * - * @param ossFilePath oss文件存储地址 + * @param objectKey oss文件存储地址 */ @Override - public OSSObject download(String ossFilePath) { - return ossUtils.download(ossFilePath); + public R downloadFile(String objectKey) { + if (ObjectUtils.isEmpty(objectKey)) { + return R.fail("objectKey is null."); + } + return ossUtils.download(objectKey); } /** * 文件删除 * - * @param ossFilePath oss文件存储地址 + * @param objectKey oss文件存储地址 */ @Override - public R delete(String ossFilePath) { + public R deleteFile(String objectKey) { try { - if (ObjectUtils.isNotEmpty(ossFilePath)) { - return ossUtils.delete(ossFilePath); + if (ObjectUtils.isNotEmpty(objectKey)) { + return ossUtils.delete(objectKey); } else { - return R.fail("ossFilePath is null."); + return R.fail("objectKey is null."); } } catch (Exception e) { return R.fail("File delete failed."); @@ -79,12 +93,14 @@ public class OssServiceImpl implements OssService { try { List ossInfos = new ArrayList<>(); for (MultipartFile multipartFile : files) { - String objectKey = multipartFile.getOriginalFilename(); + String originalFilename = Objects.requireNonNull(multipartFile.getOriginalFilename(), "文件名不能为空"); + String extension = originalFilename.substring(originalFilename.lastIndexOf('.')); + String objectKey = UuidUtils.generateUuid() + extension; File file = FileUtils.multipartFileToFile(multipartFile); objectKey = FileUtils.generateObjectName(objectKey); ossInfos.add(ossUtils.upload(objectKey, file).getData()); } - return R.ok(ossInfos); + return R.ok(ossInfos, "文件上传成功"); } catch (Exception e) { return R.fail("File upload failed."); } diff --git a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/utils/OssUtils.java b/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/utils/OssUtils.java index 7ca629d..0d33f2b 100644 --- a/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/utils/OssUtils.java +++ b/bonus-modules/bonus-oss/src/main/java/com/bonus/oss/utils/OssUtils.java @@ -6,21 +6,20 @@ import com.aliyun.oss.model.OSSObject; import com.aliyun.oss.model.ObjectMetadata; import com.bonus.common.core.domain.R; import com.bonus.common.core.text.Convert; +import com.bonus.common.core.utils.file.FileUtils; import com.bonus.oss.config.OSSConfig; import com.bonus.oss.domain.OssInfo; -import org.apache.commons.lang3.ObjectUtils; import org.apache.poi.ss.formula.functions.T; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.io.File; /** - * OSS存储工具类 + * OSS存储服务类 */ @Service public class OssUtils { @@ -31,13 +30,12 @@ public class OssUtils { private OSSConfig ossConfig; /** - * oss 客户端 + * OSS客户端 */ private OSS ossClient; /** - * 初始化信息 - * 构建OSS客户端实例 + * 初始化OSS客户端 */ @PostConstruct public void init() { @@ -45,22 +43,20 @@ public class OssUtils { } /** - * 上传文件 + * 上传文件到OSS * - * @param file File - * @return 包含上传文件信息的R对象 + * @param objectKey 文件在OSS中的键 + * @param file 要上传的文件 + * @return 包含上传文件信息的结果对象 */ public R upload(String objectKey, File file) { try { - // 上传文件到OSS ossClient.putObject(ossConfig.getBucket(), objectKey, file); - // 获取上传文件的信息并返回 - return R.ok(getInfo(objectKey)); + return R.ok(getInfo(objectKey), "文件上传成功"); } catch (Exception e) { LOGGER.error("文件上传失败", e); return R.fail("文件上传失败"); } finally { - // 删除临时文件 if (!file.delete()) { LOGGER.warn("临时文件删除失败"); } @@ -68,102 +64,73 @@ public class OssUtils { } /** - * 获取文件信息 + * 获取文件在OSS中的信息 * - * @param ossFilePath 文件路径 - * @return 包含文件信息的OssInfo对象 + * @param objectKey 文件路径 + * @return 文件信息对象 */ - public OssInfo getInfo(String ossFilePath) { + public OssInfo getInfo(String objectKey) { try { - // 获取文件的元数据 - ObjectMetadata objectMetadata = ossClient.getObjectMetadata(ossConfig.getBucket(), ossFilePath); - OssInfo ossInfo = OssInfo.builder() + ObjectMetadata objectMetadata = ossClient.getObjectMetadata(ossConfig.getBucket(), objectKey); + return OssInfo.builder() + .name(FileUtils.getName(objectKey)) .bucketName(ossConfig.getBucket()) .fileType(objectMetadata.getContentType()) .length(Convert.toStr(objectMetadata.getContentLength())) - .path(ossFilePath).build(); - return ossInfo; + .path(objectKey).build(); } catch (Exception e) { LOGGER.error("获取文件信息失败", e); - return null; + return OssInfo.builder().build(); } } /** - * 下载文件 + * 从OSS下载文件 * - * @param ossFilePath 文件路径 - * @return OSSObject对象 + * @param objectKey 文件路径 + * @return OSSObject对象,包含下载的文件 */ - public OSSObject download(String ossFilePath) { - if (ObjectUtils.isEmpty(ossFilePath)) { - return null; - } - if (!doesObjectExist(ossConfig.getBucket(), ossFilePath)) { - return null; + public R download(String objectKey) { + if (doesObjectExist(ossConfig.getBucket(), objectKey)) { + return R.fail("文件不存在"); } try { - // 从OSS下载文件 - return ossClient.getObject(ossConfig.getBucket(), ossFilePath); + return R.ok(ossClient.getObject(ossConfig.getBucket(), objectKey)); } catch (Exception e) { LOGGER.error("文件下载失败", e); - return null; + return R.fail("文件下载失败"); } } - /** - * 删除文件 + * 删除OSS中的文件 * - * @param ossFilePath 文件路径 + * @param objectKey 文件路径 + * @return 删除操作的结果 */ - public R delete(String ossFilePath) { + public R delete(String objectKey) { try { - if (!doesObjectExist(ossConfig.getBucket(), ossFilePath)) { + if (doesObjectExist(ossConfig.getBucket(), objectKey)) { return R.fail("文件不存在"); } - // 从OSS删除文件 - ossClient.deleteObject(ossConfig.getBucket(), ossFilePath); + ossClient.deleteObject(ossConfig.getBucket(), objectKey); + return R.ok(null,"文件删除成功"); } catch (Exception e) { LOGGER.error("文件删除失败", e); return R.fail("文件删除失败"); } - return R.ok(); } - /** - * 复制文件 - * - * @param source 源文件路径 - * @param path 目标文件路径 - */ - public R copy(String source, String path) { - if (!doesObjectExist(ossConfig.getBucket(), source)) { - return R.fail("文件不存在"); - } - try { - // 复制文件 - ossClient.copyObject(ossConfig.getBucket(), source, ossConfig.getBucket(), path); - return R.ok(); - } catch (Exception e) { - LOGGER.error("文件复制失败", e); - return R.fail("文件复制失败"); - } - } - - - /** - * 判断文件是否存在 + * 检查OSS中是否存在指定的文件 * * @param bucketName Bucket名称 - * @param objectName 不包含Bucket名称在内的Object完整路径 - * @return 如果文件存在则返回true,否则返回false + * @param objectKey 文件路径 + * @return 如果文件存在返回true,否则返回false */ - private boolean doesObjectExist(String bucketName, String objectName) { + private boolean doesObjectExist(String bucketName, String objectKey) { try { - // 判断文件是否存在 - return ossClient.doesObjectExist(bucketName, objectName); + return !ossClient.doesObjectExist(bucketName, objectKey); } catch (Exception e) { LOGGER.error("判断文件是否存在失败", e); return true;