新增文件分片进行上传接口

This commit is contained in:
tianliyong 2023-08-23 20:28:36 +08:00
parent cc0a0c95f3
commit 71473b3caa
10 changed files with 178 additions and 1 deletions

View File

@ -125,6 +125,27 @@ public class WebFileController {
return CommonResponse.success(BeanConvertUtil.copyBean(response, MultipartUploadVo.class));
}
@SneakyThrows
@PostMapping(value = "/v1/multipart-upload/file", consumes = MULTIPART_FORM_DATA_VALUE)
@CrossOrigin
public CommonResponse<MultipartUploadFileVo> multipartUploadFile(@Valid @RequestParam("appCode") String appCode,
@Valid @RequestParam("bizScene") String bizScene,
@Valid @RequestParam("fileName") String fileName,
@Valid @RequestParam("tgtFileKey") String tgtFileKey,
@Valid @RequestParam("uploadId") String uploadId,
@Valid @RequestPart MultipartFile file) {
MultipartUploadFileDto dto = MultipartUploadFileDto.builder()
.appCode(appCode)
.bizScene(bizScene)
.fileName(fileName)
.tgtFileKey(tgtFileKey)
.fileContent(file.getBytes())
.uploadId(uploadId)
.build();
MultipartUploadFileResponse response = fileService.multipartUploadFile(dto);
return CommonResponse.success(BeanConvertUtil.copyBean(response, MultipartUploadFileVo.class));
}
@PostMapping("/v1/multipart-upload/complete")
@CrossOrigin
@SneakyThrows

View File

@ -0,0 +1,19 @@
package cn.axzo.oss.client.vo;
import cn.axzo.oss.manager.api.dto.PartETag;
import lombok.Data;
import java.util.List;
/**
* @Author: liyong.tian
* @Date: 2023/8/15 11:56
* @Description:
*/
@Data
public class MultipartUploadFileVo {
private String uploadId;
private List<PartETag> partETags;
}

View File

@ -62,4 +62,6 @@ public interface BaseS3Service {
Integer partNumber, long partSize);
String multipartUploadComplete(String bucketName, String tgtFileKey, String uploadId, List<PartETag> partETags);
List<PartETag> multipartUploadFile(String bucketName, String tgtFileKey, String uploadId, byte[] fileContent);
}

View File

@ -15,9 +15,11 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.FilterInputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import static cn.axzo.oss.common.constans.CommonConstants.APP_PRO_BUCKET_NAME;
@ -193,6 +195,52 @@ public class AliOssServiceImpl implements AliOssService {
}
}
@Override
public List<PartETag> multipartUploadFile(String bucketName, String tgtFileKey, String uploadId, byte[] fileContent) {
OSS client = aliOssClient.getClient();
try {
List<PartETag> partETags = new ArrayList<PartETag>();
// 每个分片的大小用于计算文件有多少个分片单位为字节
final long partSize = 10 * 1024 * 1024L; //1 MB
// 根据上传的数据大小计算分片数以本地文件为例说明如何通过File.length()获取上传数据的大小
long fileLength = fileContent.length;
int partCount = (int) (fileLength / partSize);
if (fileLength % partSize != 0) {
partCount++;
}
// 遍历分片上传
for (int i = 0; i < partCount; i++) {
long startPos = i * partSize;
long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
UploadPartRequest partRequest = new UploadPartRequest();
// 阿里云 oss 文件根目录
partRequest.setBucketName(bucketName);
// 文件key
partRequest.setKey(tgtFileKey);
// 分片上传uploadId
partRequest.setUploadId(uploadId);
// 分片文件
InputStream inputStream = new ByteArrayInputStream(fileContent);
inputStream.skip(startPos);
partRequest.setInputStream(inputStream);
// 分片大小除了最后一个分片没有大小限制其他的分片最小为100 KB
partRequest.setPartSize(curPartSize);
// 分片号每一个上传的分片都有一个分片号取值范围是1~10000如果超出这个范围OSS将返回InvalidArgument的错误码
partRequest.setPartNumber(i + 1);
// 每个分片不需要按顺序上传甚至可以在不同客户端上传OSS会按照分片号排序组成完整的文件
UploadPartResult uploadPartResult = client.uploadPart(partRequest);
// 每次上传分片之后OSS的返回结果包含PartETagPartETag将被保存在partETags中
partETags.add(uploadPartResult.getPartETag());
}
return partETags;
} catch (Exception e) {
e.printStackTrace();
throw new BizException(MULTIPART_UPLOAD_ERROR);
}
}
@Override
public String multipartUploadComplete(String bucketName, String tgtFileKey, String uploadId, List<PartETag> partETags) {
OSS client = aliOssClient.getClient();

View File

@ -2,6 +2,7 @@ package cn.axzo.oss.manager.api;
import cn.axzo.oss.manager.api.dto.PartETag;
import cn.axzo.oss.manager.api.dto.request.MultipartUploadDto;
import cn.axzo.oss.manager.api.dto.request.MultipartUploadFileDto;
import java.io.InputStream;
import java.util.List;
@ -46,4 +47,6 @@ public interface FileManager {
PartETag multipartUpload(String bucketName, String tgtFileKey, byte[] fileContent, MultipartUploadDto dto);
String multipartUploadComplete(String bucketName, String tgtFileKey, String uploadId, List<PartETag> partETags);
List<PartETag> multipartUploadFile(String bucketName, String tgtFileKey, byte[] fileContent, MultipartUploadFileDto dto);
}

View File

@ -0,0 +1,39 @@
package cn.axzo.oss.manager.api.dto.request;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
/**
* @Author: liyong.tian
* @Date: 2023/8/15 11:39
* @Description:
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MultipartUploadFileDto {
@NotBlank
private String appCode;
@NotBlank
private String bizScene;
@NotBlank
private String fileName;
@NotBlank
private String tgtFileKey;
private byte[] fileContent;
/**
* oss上传时的上传id
*/
private String uploadId;
}

View File

@ -0,0 +1,22 @@
package cn.axzo.oss.manager.api.dto.response;
import cn.axzo.oss.manager.api.dto.PartETag;
import lombok.Builder;
import lombok.Data;
import java.util.List;
/**
* @Author: liyong.tian
* @Date: 2023/8/15 13:39
* @Description:
*/
@Data
@Builder
public class MultipartUploadFileResponse {
private String uploadId;
private List<PartETag> partETags;
}

View File

@ -5,6 +5,7 @@ import cn.axzo.oss.integration.s3.AliOssService;
import cn.axzo.oss.manager.api.FileManager;
import cn.axzo.oss.manager.api.dto.PartETag;
import cn.axzo.oss.manager.api.dto.request.MultipartUploadDto;
import cn.axzo.oss.manager.api.dto.request.MultipartUploadFileDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -70,6 +71,12 @@ public class FileManagerImpl implements FileManager {
return BeanConvertUtil.copyBean(partETag, PartETag.class);
}
@Override
public List<PartETag> multipartUploadFile(String bucketName, String tgtFileKey, byte[] fileContent, MultipartUploadFileDto dto) {
List<com.aliyun.oss.model.PartETag> partETags = aliOssService.multipartUploadFile(bucketName, tgtFileKey, dto.getUploadId(), dto.getFileContent());
return BeanConvertUtil.copyList(partETags, PartETag.class);
}
@Override
public String multipartUploadComplete(String bucketName, String tgtFileKey, String uploadId, List<PartETag> partETags) {
List<com.aliyun.oss.model.PartETag> partETagList = convertPartETags(partETags);

View File

@ -42,4 +42,6 @@ public interface FileService {
MultipartUploadResponse multipartUpload(MultipartUploadDto dto);
FileInformationResponse multipartUploadComplete(MultipartUploadCompleteDto dto);
MultipartUploadFileResponse multipartUploadFile(MultipartUploadFileDto dto);
}

View File

@ -10,7 +10,6 @@ import cn.axzo.oss.common.enums.CodeEnum;
import cn.axzo.oss.common.enums.FileClassEnum;
import cn.axzo.oss.common.enums.FileStatusEnum;
import cn.axzo.oss.common.exception.BizException;
import cn.axzo.oss.common.utils.BeanConvertUtil;
import cn.axzo.oss.common.utils.JsonUtil;
import cn.axzo.oss.common.utils.Utility;
import cn.axzo.oss.dal.entity.*;
@ -181,6 +180,21 @@ public class FileServiceImpl implements FileService {
return response;
}
@Override
public MultipartUploadFileResponse multipartUploadFile(MultipartUploadFileDto dto) {
FileUploadConfig fileUploadConfig = getFileUploadConfig(dto.getAppCode(), dto.getBizScene());
// 判断容量
isFileConform(fileUploadConfig, dto.getFileContent().length, dto.getFileName());
List<PartETag> partETags = fileManager.multipartUploadFile(fileUploadConfig.getBucketName(),
dto.getTgtFileKey(), dto.getFileContent(), dto);
MultipartUploadFileResponse response = MultipartUploadFileResponse.builder()
.uploadId(dto.getUploadId())
.partETags(partETags)
.build();
return response;
}
@Override
public FileInformationResponse multipartUploadComplete(MultipartUploadCompleteDto dto) {
FileUploadConfig fileUploadConfig = getFileUploadConfig(dto.getAppCode(), dto.getBizScene());