Merge branch 'feature/bug-523' into develop

This commit is contained in:
曹鹏飞 2025-07-24 14:17:52 +08:00
commit 5fe030e663
4 changed files with 109 additions and 6 deletions

View File

@ -32,6 +32,7 @@ import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -42,7 +43,9 @@ import java.nio.file.Path;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
@ -66,6 +69,8 @@ public class FileController extends ControllerBase {
@Resource @Resource
private IFileUploadRecordService fileUploadRecordService; private IFileUploadRecordService fileUploadRecordService;
private static final Map<String,String> FILE_PATH_MAP=new HashMap<>();
/** /**
* 上传单个文件 * 上传单个文件
* @param file 要上传的文件 * @param file 要上传的文件
@ -229,4 +234,54 @@ public class FileController extends ControllerBase {
.contentType(MediaType.APPLICATION_OCTET_STREAM) .contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(zipContent); .body(zipContent);
} }
/**
* 初始化分片上传
* @param fileName 文件名
* @return uploadId
*/
@GetMapping("/multipart/init")
public ApiResult<String> 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<Void> 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<String> 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);
}
} }

View File

@ -1,10 +1,11 @@
spring.application.name=admin spring.application.name=admin
spring.profiles.active=dev spring.profiles.active=dev
server.port=8082 server.port=8082
# 设置最大文件大小 (默认为1MB) spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=100MB spring.servlet.multipart.max-file-size=1024MB
# 设置所有文件总大小 (默认为10MB) spring.servlet.multipart.max-request-size=1024MB
spring.servlet.multipart.max-request-size=500MB 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=classpath:application-${spring.profiles.active}.properties,nacos:
#spring.config.import=nacos: #spring.config.import=nacos:
logging.level.root=info logging.level.root=info

View File

@ -24,4 +24,12 @@ public interface FileUploadService {
* @throws IOException * @throws IOException
*/ */
String upload(String filePath, InputStream stream) 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);
} }

View File

@ -2,8 +2,7 @@ package com.nflg.mobilebroken.starter.service.impl;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS; import com.aliyun.oss.OSS;
import com.aliyun.oss.model.PutObjectRequest; import com.aliyun.oss.model.*;
import com.aliyun.oss.model.PutObjectResult;
import com.nflg.mobilebroken.starter.service.FileUploadService; import com.nflg.mobilebroken.starter.service.FileUploadService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -14,6 +13,8 @@ import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@Service @Service
@ConditionalOnProperty(name = "file.upload.type", havingValue = "oss") @ConditionalOnProperty(name = "file.upload.type", havingValue = "oss")
@ -41,4 +42,42 @@ public class OSSFileUploadService implements FileUploadService {
//log.debug("上传文件结果: " + result); //log.debug("上传文件结果: " + result);
return StrUtil.format("{}/{}",domain, filePath); 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<PartETag> 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);
}
} }