From 63bb718b31fd6e2a9e54723599880b998f7a85ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9B=B9=E9=B9=8F=E9=A3=9E?= Date: Wed, 23 Jul 2025 14:45:37 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E4=B8=8A=E4=BC=A0=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E6=9C=80=E5=A4=A7=E6=94=AF=E6=8C=811GB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/bootstrap.properties | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nflg-mobilebroken-admin/src/main/resources/bootstrap.properties b/nflg-mobilebroken-admin/src/main/resources/bootstrap.properties index d77293c8..e9884884 100644 --- a/nflg-mobilebroken-admin/src/main/resources/bootstrap.properties +++ b/nflg-mobilebroken-admin/src/main/resources/bootstrap.properties @@ -1,10 +1,11 @@ spring.application.name=admin spring.profiles.active=dev server.port=8082 -# 设置最大文件大小 (默认为1MB) -spring.servlet.multipart.max-file-size=100MB -# 设置所有文件总大小 (默认为10MB) -spring.servlet.multipart.max-request-size=500MB +spring.servlet.multipart.enabled=true +spring.servlet.multipart.max-file-size=1024MB +spring.servlet.multipart.max-request-size=1024MB +spring.servlet.multipart.file-size-threshold=10MB +spring.servlet.multipart.location=/tmp #spring.config.import=classpath:application-${spring.profiles.active}.properties,nacos: #spring.config.import=nacos: logging.level.root=info From 7a2b031d43a80007d7881bb5299d3b2f41c0adec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9B=B9=E9=B9=8F=E9=A3=9E?= Date: Thu, 24 Jul 2025 14:16:46 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20bug-523=20=E6=94=AF=E6=8C=811GB?= =?UTF-8?q?=E5=A4=A7=E6=96=87=E4=BB=B6=E7=9A=84=E5=88=86=E7=89=87=E6=96=AD?= =?UTF-8?q?=E7=82=B9=E7=BB=AD=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/controller/FileController.java | 55 +++++++++++++++++++ .../starter/service/FileUploadService.java | 8 +++ .../service/impl/OSSFileUploadService.java | 43 ++++++++++++++- 3 files changed, 104 insertions(+), 2 deletions(-) diff --git a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/FileController.java b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/FileController.java index 7d7c16ab..ef051a76 100644 --- a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/FileController.java +++ b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/FileController.java @@ -32,6 +32,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.validation.Valid; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.io.FileOutputStream; @@ -42,7 +43,9 @@ import java.nio.file.Path; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -66,6 +69,8 @@ public class FileController extends ControllerBase { @Resource private IFileUploadRecordService fileUploadRecordService; + private static final Map FILE_PATH_MAP=new HashMap<>(); + /** * 上传单个文件 * @param file 要上传的文件 @@ -229,4 +234,54 @@ public class FileController extends ControllerBase { .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(zipContent); } + + /** + * 初始化分片上传 + * @param fileName 文件名 + * @return uploadId + */ + @GetMapping("/multipart/init") + public ApiResult initMultipartUpload(@Valid @RequestParam @NotBlank String fileName) { + String filePath=buildFilePath(getFileType(fileName)); + String uploadId=fileUploadService.initMultipartUpload(filePath); + FILE_PATH_MAP.put(uploadId,filePath); + return ApiResult.success(uploadId); + } + + /** + * 上传分片 + * @param file 要上传的分片文件,名称为file + * @param uploadId 上传id + * @param chunkNumber 分片编号 + */ + @PostMapping("/multipart/uploadChunk") + public ApiResult uploadChunk(@RequestParam("file") MultipartFile file, @RequestParam String uploadId, @RequestParam Integer chunkNumber) throws IOException { + String filePath = FILE_PATH_MAP.get(uploadId); + VUtils.trueThrowBusinessError(StrUtil.isBlank(filePath)).throwMessage("文件不存在"); + fileUploadService.uploadChunk(file,filePath, uploadId, chunkNumber); + return ApiResult.success(); + } + + /** + * 完成分片上传 + * @param uploadId 上传id + * @return 文件url + */ + @PostMapping("/multipart/complete") + public ApiResult completeMultipartUpload(@RequestParam String uploadId) { + String filePath = FILE_PATH_MAP.get(uploadId); + VUtils.trueThrowBusinessError(StrUtil.isBlank(filePath)).throwMessage("文件不存在"); + return ApiResult.success(fileUploadService.completeMultipartUpload(filePath, uploadId)); + } + + /** + * 取消分片上传 + * @param uploadId 上传id + */ + @PostMapping("/multipart/abort") + public void abortMultipartUpload(@RequestParam String uploadId) { + String filePath = FILE_PATH_MAP.get(uploadId); + VUtils.trueThrowBusinessError(StrUtil.isBlank(filePath)).throwMessage("文件不存在"); + fileUploadService.abortMultipartUpload(filePath, uploadId); + } } diff --git a/nflg-mobilebroken-starter/src/main/java/com/nflg/mobilebroken/starter/service/FileUploadService.java b/nflg-mobilebroken-starter/src/main/java/com/nflg/mobilebroken/starter/service/FileUploadService.java index c0d944bd..d3086451 100644 --- a/nflg-mobilebroken-starter/src/main/java/com/nflg/mobilebroken/starter/service/FileUploadService.java +++ b/nflg-mobilebroken-starter/src/main/java/com/nflg/mobilebroken/starter/service/FileUploadService.java @@ -24,4 +24,12 @@ public interface FileUploadService { * @throws IOException */ String upload(String filePath, InputStream stream) throws IOException; + + String initMultipartUpload(String filePath); + + void uploadChunk(MultipartFile file,String filePath,String uploadId, int chunkNumber) throws IOException; + + String completeMultipartUpload(String filePath,String uploadId); + + void abortMultipartUpload(String filePath,String uploadId); } \ No newline at end of file diff --git a/nflg-mobilebroken-starter/src/main/java/com/nflg/mobilebroken/starter/service/impl/OSSFileUploadService.java b/nflg-mobilebroken-starter/src/main/java/com/nflg/mobilebroken/starter/service/impl/OSSFileUploadService.java index d7e9fe1a..6eb10f96 100644 --- a/nflg-mobilebroken-starter/src/main/java/com/nflg/mobilebroken/starter/service/impl/OSSFileUploadService.java +++ b/nflg-mobilebroken-starter/src/main/java/com/nflg/mobilebroken/starter/service/impl/OSSFileUploadService.java @@ -2,8 +2,7 @@ package com.nflg.mobilebroken.starter.service.impl; import cn.hutool.core.util.StrUtil; import com.aliyun.oss.OSS; -import com.aliyun.oss.model.PutObjectRequest; -import com.aliyun.oss.model.PutObjectResult; +import com.aliyun.oss.model.*; import com.nflg.mobilebroken.starter.service.FileUploadService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -14,6 +13,8 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; @Service @ConditionalOnProperty(name = "file.upload.type", havingValue = "oss") @@ -41,4 +42,42 @@ public class OSSFileUploadService implements FileUploadService { //log.debug("上传文件结果: " + result); return StrUtil.format("{}/{}",domain, filePath); } + + @Override + public String initMultipartUpload(String filePath) { + InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, filePath); + InitiateMultipartUploadResult result = ossClient.initiateMultipartUpload(request); + return result.getUploadId(); + } + + @Override + public void uploadChunk(MultipartFile file,String filePath,String uploadId, int chunkNumber) throws IOException { + UploadPartRequest uploadPartRequest = new UploadPartRequest(); + uploadPartRequest.setBucketName(bucketName); + uploadPartRequest.setKey(filePath); + uploadPartRequest.setUploadId(uploadId); + uploadPartRequest.setInputStream(file.getInputStream()); + uploadPartRequest.setPartSize(file.getSize()); + uploadPartRequest.setPartNumber(chunkNumber); + ossClient.uploadPart(uploadPartRequest); + } + + @Override + public String completeMultipartUpload(String filePath,String uploadId) { + ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, filePath, uploadId); + PartListing partListing = ossClient.listParts(listPartsRequest); + List partETags = new ArrayList<>(); + for (PartSummary part : partListing.getParts()) { + partETags.add(new PartETag(part.getPartNumber(), part.getETag())); + } + CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(bucketName, filePath, uploadId, partETags); + ossClient.completeMultipartUpload(completeRequest); + return StrUtil.format("{}/{}",domain, filePath); + } + + @Override + public void abortMultipartUpload(String filePath,String uploadId) { + AbortMultipartUploadRequest abortRequest = new AbortMultipartUploadRequest(bucketName, filePath, uploadId); + ossClient.abortMultipartUpload(abortRequest); + } }