From 6e627271dfbdc6736ece12f259f6afdc5c2f6b3c Mon Sep 17 00:00:00 2001 From: wenbaoquan <1150003126@qq.com> Date: Tue, 10 Jan 2023 09:24:28 +0800 Subject: [PATCH] =?UTF-8?q?2023=E5=B9=B41=E6=9C=8810=E6=97=A509:24:17?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 11 + .../zilber/boot/file/entity/OssCancel.java | 30 + .../zilber/boot/file/entity/OssComplete.java | 37 + .../zilber/boot/file/entity/OssListParts.java | 36 + .../boot/file/entity/OssPartUpload.java | 44 ++ .../boot/file/entity/OssProperties.java | 40 ++ .../zilber/boot/file/service/UploadUtils.java | 644 ++++++++++++++++++ 7 files changed, 842 insertions(+) create mode 100644 src/main/java/com/zilber/boot/file/entity/OssCancel.java create mode 100644 src/main/java/com/zilber/boot/file/entity/OssComplete.java create mode 100644 src/main/java/com/zilber/boot/file/entity/OssListParts.java create mode 100644 src/main/java/com/zilber/boot/file/entity/OssPartUpload.java create mode 100644 src/main/java/com/zilber/boot/file/entity/OssProperties.java create mode 100644 src/main/java/com/zilber/boot/file/service/UploadUtils.java diff --git a/pom.xml b/pom.xml index 7c6a984..eb904af 100644 --- a/pom.xml +++ b/pom.xml @@ -193,6 +193,11 @@ ${knife4j.version} + + org.projectlombok + lombok + + @@ -236,6 +241,12 @@ ${jwt.version} + + com.aliyun.oss + aliyun-sdk-oss + 3.15.1 + + diff --git a/src/main/java/com/zilber/boot/file/entity/OssCancel.java b/src/main/java/com/zilber/boot/file/entity/OssCancel.java new file mode 100644 index 0000000..c50d639 --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/OssCancel.java @@ -0,0 +1,30 @@ +package com.zilber.boot.file.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.stereotype.Component; + +import javax.validation.constraints.NotBlank; + +/** + * @Author LJX + * @TIME 2023-01-09 16:04 + * @PROJECT cppcc + * created by Intellij IDEA + * Description + */ +@Data +@ApiModel("oss分片上传取消") +@Component +public class OssCancel extends OssProperties{ + + @NotBlank(message = "上传id不能为空") + @ApiModelProperty(value = "上传id", required = true) + private String uploadId; + + @NotBlank(message = "文件名称不能为空") + @ApiModelProperty(value = "文件名称", required = true) + private String key; + +} diff --git a/src/main/java/com/zilber/boot/file/entity/OssComplete.java b/src/main/java/com/zilber/boot/file/entity/OssComplete.java new file mode 100644 index 0000000..8e09398 --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/OssComplete.java @@ -0,0 +1,37 @@ +package com.zilber.boot.file.entity; + +import com.aliyun.oss.model.PartETag; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.stereotype.Component; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @Author LJX + * @TIME 2023-01-09 15:52 + * @PROJECT cppcc + * created by Intellij IDEA + * Description + */ +@Data +@Component +@ApiModel("oss分片上传完成合并请求") +public class OssComplete extends OssProperties{ + + @NotBlank(message = "上传id不能为空") + @ApiModelProperty(value = "上传id", required = true) + private String uploadId; + + @NotBlank(message = "文件名称不能为空") + @ApiModelProperty(value = "文件名称", required = true) + private String key; + + @NotNull(message = "tag列表不能为空") + @ApiModelProperty("tag列表") + private List tags; + +} diff --git a/src/main/java/com/zilber/boot/file/entity/OssListParts.java b/src/main/java/com/zilber/boot/file/entity/OssListParts.java new file mode 100644 index 0000000..62f733f --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/OssListParts.java @@ -0,0 +1,36 @@ +package com.zilber.boot.file.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.stereotype.Component; + +import javax.validation.constraints.NotBlank; + +/** + * @Author LJX + * @TIME 2023-01-09 16:19 + * @PROJECT cppcc + * created by Intellij IDEA + * Description + */ +@Data +@Component +@ApiModel("oss获取切片列表") +public class OssListParts extends OssProperties { + + @NotBlank(message = "上传id不能为空") + @ApiModelProperty(value = "上传id", required = true) + private String uploadId; + + @NotBlank(message = "文件名称不能为空") + @ApiModelProperty(value = "文件名称", required = true) + private String key; + + @ApiModelProperty(value = "每页块数") + private Integer maxParts = 100; + + @ApiModelProperty(value = "开始块数") + private Integer partNumberMarker = 0; + +} diff --git a/src/main/java/com/zilber/boot/file/entity/OssPartUpload.java b/src/main/java/com/zilber/boot/file/entity/OssPartUpload.java new file mode 100644 index 0000000..04f869a --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/OssPartUpload.java @@ -0,0 +1,44 @@ +package com.zilber.boot.file.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @Author LJX + * @TIME 2023-01-09 15:03 + * @PROJECT cppcc + * created by Intellij IDEA + * Description + */ +@Data +@Component +@ApiModel("oss分片上传") +public class OssPartUpload extends OssProperties{ + + @NotNull(message = "未上传文件") + @ApiModelProperty(value = "文件", required = true) + private MultipartFile file; + + @NotBlank(message = "上传id不能为空") + @ApiModelProperty(value = "上传id", required = true) + private String uploadId; + + @NotBlank(message = "文件名称不能为空") + @ApiModelProperty(value = "文件名称", required = true) + private String key; + + @NotNull(message = "分页号不能为空") + @ApiModelProperty(value = "分页号", required = true) + private int partNumber; + + @NotNull(message = "分页大小不能为空") + @ApiModelProperty(value = "分页大小", required = true) + private long partSize; + +} diff --git a/src/main/java/com/zilber/boot/file/entity/OssProperties.java b/src/main/java/com/zilber/boot/file/entity/OssProperties.java new file mode 100644 index 0000000..cf665a8 --- /dev/null +++ b/src/main/java/com/zilber/boot/file/entity/OssProperties.java @@ -0,0 +1,40 @@ +package com.zilber.boot.file.entity; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @Author LJX + * @TIME 2023-01-09 9:57 + * @PROJECT cppcc + * created by Intellij IDEA + * Description + */ +@Component +@Data +@ConfigurationProperties("aliyun.oss") +public class OssProperties { + + /** + * 填写Bucket所在地域对应的Endpoint + */ + private String endpoint; + /** + * AccessKey的id + */ + private String keyId; + /** + * AccessKey的密钥 + */ + private String keySecret; + /** + * 阿里云储存文件的Bucket名称 + */ + private String bucketName; + /** + * 目标文件夹名称 + */ + private String module; + +} diff --git a/src/main/java/com/zilber/boot/file/service/UploadUtils.java b/src/main/java/com/zilber/boot/file/service/UploadUtils.java new file mode 100644 index 0000000..f45226c --- /dev/null +++ b/src/main/java/com/zilber/boot/file/service/UploadUtils.java @@ -0,0 +1,644 @@ +package com.zilber.boot.file.service; + +import com.aliyun.oss.*; +import com.aliyun.oss.model.*; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.cppcc.common.validator.ValidatorUtils; +import com.cppcc.files.*; +import com.cppcc.files.dao.FileDao; +import com.zilber.boot.file.entity.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import reactor.util.annotation.Nullable; + +import javax.annotation.Resource; +import java.io.*; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @Author LJX + * @TIME 2023-01-09 9:11 + * @PROJECT cppcc + * created by Intellij IDEA + * Description + */ +@Service +@Slf4j +public class UploadUtils { + + @Value("${cppcc.localtion}") + private String localtion; + + @Resource + private OssProperties ossProperties; + + @Autowired + private FileDao fileDao; + + public Map upload(MultipartFile file) { + try { + String type = "." + FilenameUtils.getExtension(file.getOriginalFilename()); + String name = FilenameUtils.getName(file.getOriginalFilename()); + String filePath = localtion + "/upload"; + String fileName = UUID.randomUUID() + type; + File desc = getAbsoluteFile(filePath, fileName); + file.transferTo(desc); + return getPathFileName(filePath, fileName, name, type); + } catch (Exception e) { + log.error(e.getLocalizedMessage()); + return new ConcurrentHashMap<>(); + } + } + + private Map getPathFileName(String uploadDir, String fileName, String name, String type) throws IOException { + Map map = new ConcurrentHashMap(3); + int dirLastIndex = localtion.length() + 1; + String currentDir = StringUtils.substring(uploadDir, dirLastIndex); + String pathFileName = "/profile" + "/" + currentDir + "/" + fileName; + map.put("url", pathFileName); + map.put("name", name); + map.put("type", String.valueOf(SliceUploadsTemplate.getFileType(type))); + return map; + } + + private File getAbsoluteFile(String uploadDir, String fileName) { + File desc = new File(uploadDir + File.separator + fileName); + if (!desc.exists()) { + if (!desc.getParentFile().exists()) { + desc.getParentFile().mkdirs(); + } + } + return desc; + } + + //TODO 上传至oss + /** + * 上传文件 + * + * @param file 上传的文件 + * @param module oss目录 + * @return + */ + public PutObjectResult upload(MultipartFile file, @Nullable String module) { + /** + * 获取oss的属性 + */ + String endpoint = ossProperties.getEndpoint(); + String accessKeyId = ossProperties.getKeyId(); + String accessKeySecret = ossProperties.getKeySecret(); + String bucketName = ossProperties.getBucketName(); + if ( StringUtils.isBlank(module) ){ + module = ossProperties.getModule(); + } + String extension = file.getName().substring(file.getName().lastIndexOf(".")); + String objectName = module + "/" + UUID.randomUUID().toString() + extension; + + // 创建OSSClient实例。 + OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); + try { + // 创建PutObjectRequest对象。 + PutObjectRequest putObjectRequest + = new PutObjectRequest(bucketName, objectName, file.getInputStream()); + // 设置该属性可以返回response。如果不设置,则返回的response为空。 + putObjectRequest.setProcess("true"); + // 上传字符串。 + PutObjectResult result = ossClient.putObject(putObjectRequest); + return result; + } catch (OSSException oe) { + throw new ServiceException(oe.getMessage()); + } catch (ClientException ce) { + throw new ServiceException(ce.getMessage()); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (ossClient != null) { + // 关闭OSSClient。 + ossClient.shutdown(); + } + } + return null; + } + + //TODO 分片上传至服务器 + /** + * 清除临时目录下的临时文件 + * + * @param root + */ + private void clearTempFiles(File root) { + File[] files = root.listFiles(); + if (files != null) { + List fileList = Arrays.asList(files); + for (File f : fileList) { + f.delete(); + } + } + root.delete(); + } + + /********************************************************************************************/ + + public FileUploadDTO sliceUploads(FileUploadsRequestDTO param) { + boolean isOk = true; + File root = new File(localtion + "/upload", param.getUUID()); + if (!root.exists() || !root.isDirectory()) { + isOk = root.mkdirs(); + } + File targetFile = new File(localtion + "/upload", param.getUUID() + param.getType()); + if (!targetFile.exists() || !targetFile.isFile()) { + try { + targetFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + Map map = new HashMap<>(); + map.put(param.getChunk(), param.getUUID()); + if (isOk) { + String sliceName = param.getChunk().toString(); + upload(root, sliceName, param); + } + return FileUploadDTO.builder().chunkMd5Info(map).build(); + } + + /** + * 文件检测 + * + * @param md5 md5 + * @param UUID UUID + * @return + * @throws IOException + */ + public FileCheckDTO fileCheck(String md5, String UUID) throws IOException { + FileCheckDTO fileCheckDTO = new FileCheckDTO(); + //根据文件md5查询文件是否存在,如果存在,则直接返回文件路径,否则返回块信息 + //TODO + Map objectMap = fileDao.listFileUrl(md5); + if (objectMap != null) { + fileCheckDTO.setUrl(objectMap.get("url").toString()); + fileCheckDTO.setType(Integer.parseInt(objectMap.get("type").toString())); + fileCheckDTO.setExist(true); + return fileCheckDTO; + } + //不存在 + return checkUnexist(UUID, fileCheckDTO); + } + + /** + * @return + * @author liuao + */ + public boolean upload(File root, String name, FileUploadsRequestDTO param) { + //保存最大块数 + File aConfFile = new File(root.getAbsolutePath(), param.getUUID() + ".conf"); + File sizeFile = new File(root.getAbsolutePath(), "size.conf"); + if (!aConfFile.exists()) { + FileWriter w = null; + try { + aConfFile.createNewFile(); + w = new FileWriter(aConfFile); + w.write(param.getChunks().toString()); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + assert w != null; + w.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + RandomAccessFile accessTmpFile = null; + int length = 0; + File[] files = root.listFiles(); + if (files != null) { + length = files.length; + } +// String uploadDirPath = localtion + "/upload"; + File tmpFile = new File(root.getAbsolutePath(), name); + File tmpConfFile = new File(root.getAbsolutePath(), name + ".conf"); + try { + accessTmpFile = new RandomAccessFile(tmpFile, "rw"); + accessTmpFile.write(param.getFile().getBytes()); + log.info(param.getUUID() + "文件块" + param.getChunk() + "上传完成"); + return true; + } catch (IOException e) { + log.error(e.getMessage(), e); + if (tmpConfFile.exists()) { + tmpConfFile.delete(); + } + } finally { + try { + if (tmpFile.length() == param.getFile().getSize()) { + if (!tmpConfFile.exists()) { + tmpConfFile.createNewFile(); + } + } + assert accessTmpFile != null; + accessTmpFile.close(); + } catch (IOException e) { + log.error(e.getLocalizedMessage()); + if (tmpConfFile.exists()) { + tmpConfFile.delete(); + } + } + } + return false; + } + + public FileCheckDTO compose(String UUID, String type, String md5) { + long startTime = 0, endTime = 0; + log.info(String.valueOf(System.currentTimeMillis())); + FileCheckDTO fileCheckDTO = new FileCheckDTO(); + File root = new File(localtion + "/upload", UUID); + File targetFile = new File(localtion + "/upload", UUID + type); + Long chunks = chunks(root, UUID); + File[] fileNames = root.listFiles((file1, s1) -> !s1.endsWith(".conf")); + if (fileNames == null || fileNames.length < chunks) { + return checkUnexist(UUID, new FileCheckDTO()); + } + List collect = Arrays.asList(fileNames) + .stream().sorted(new Comparator() { + @Override + public int compare(File file, File t1) { + int f = Integer.parseInt(file.getName()); + int t = Integer.parseInt(t1.getName()); + return f < t ? -1 : 1; + } + }).collect(Collectors.toList()); + FileOutputStream fos; + FileInputStream fis; + // 一次读取10M数据,将读取到的数据保存到byte字节数组中 + byte[] buffer = new byte[1024 * 1024 * 10]; + int len; + try { + fos = new FileOutputStream(targetFile); + log.info(String.valueOf(startTime = System.currentTimeMillis())); + for (File file : collect) { + fis = new FileInputStream(file); + len = 0; + while ((len = fis.read(buffer)) != -1) { + // buffer从指定字节数组写入。buffer:数据中的起始偏移量,len:写入的字数。 + fos.write(buffer, 0, len); + } + fos.flush(); + fis.close(); + } + fos.close(); + log.info("传输完成:" + (endTime = System.currentTimeMillis())); + } catch (IOException ex) { + targetFile.delete(); + ex.printStackTrace(); + } + log.info(String.valueOf(endTime - startTime)); +// String fileName = java.util.UUID.randomUUID().toString(); + int dirLastIndex = localtion.length() + 1; + String currentDir = StringUtils.substring(localtion + "/upload", dirLastIndex); + String pathFileName = "/profile" + "/" + currentDir + "/" + UUID + type; + Integer t = getFileType(type); + fileDao.addFile(md5, pathFileName, t); + fileCheckDTO.setUrl(pathFileName); + fileCheckDTO.setType(t); + fileCheckDTO.setExist(true); + clearTempFiles(root); + return fileCheckDTO; + } + + private FileCheckDTO checkUnexist(String UUID, FileCheckDTO fileCheckDTO) { + //不存在 + fileCheckDTO.setExist(false); + File root = new File(localtion + "/upload", UUID); + if (!root.exists()) { + fileCheckDTO.setUploaded(false); + return fileCheckDTO; + } + //获取总块数 +// File aConf = new File(root.getAbsolutePath(), UUID + ".conf"); +// FileReader fr = new FileReader(aConf); +// char[] chunkCs = new char[(int) aConf.length()]; +// fr.read(chunkCs); + Long chunks = chunks(root, UUID); + FilenameFilter filter = new FilenameFilter() { + @Override + public boolean accept(File file, String s) { + return s.endsWith(".conf") && !s.contains("-"); + } + }; + String[] fileNames = root.list(filter); + if (fileNames == null) { + fileCheckDTO.setUploaded(false); + return fileCheckDTO; + } + List fileNameList = Arrays.asList(fileNames) + .stream().distinct().collect(Collectors.toList()); + Map chunkInfo = new HashMap<>(); + if (CollectionUtils.isNotEmpty(fileNameList)) { + for (String fileName : fileNameList) { + String prefix = fileName.split("\\.")[0]; + chunkInfo.put(prefix, true); + } + fileCheckDTO.setChunkInfo(chunkInfo); + fileCheckDTO.setUploaded(true); + fileCheckDTO.setChunks(chunks); + return fileCheckDTO; + } + fileCheckDTO.setUploaded(false); + return fileCheckDTO; + } + + private Long chunks(File root, String UUID) { + File aConf = new File(root.getAbsolutePath(), UUID + ".conf"); + FileReader fr = null; + char[] chunkCs = null; + try { + fr = new FileReader(aConf); + chunkCs = new char[(int) aConf.length()]; + fr.read(chunkCs); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + fr.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return Long.valueOf(String.valueOf(chunkCs)); + } + + public static Integer getFileType(String type) { + String pic = ".jpeg,.bmp,.jpg,.png,.tif,.gif,.pcx,.tga,.exif,.fpx,.svg,.psd,.cdr,.pcd,.dxf,.ufo,.eps,.ai,.raw,.WMF,.webp,.avif,.apng"; + String video = ".wmv,.asf,.asx,.mp4,.m4v,.rm,.rmvb,.mpg,.mpeg,.mpe,.3gp,.mov,.avi,.dat,.mkv,.flv,.vob"; + if (pic.contains(type)) { + return 1; + } + if (video.contains(type)) { + return 3; + } + return 2; + } + + //TODO 分片上传至oss + + /** + * 初始化切片上传 + * @param fileName 文件名 + * @param module 目标文件夹 + * @return 文件唯一标识 + */ + public OssPartUpload InitiateMultipartUpload(String fileName, @Nullable String module, OssProperties provided) { + /** + * 获取oss的属性 + */ + String endpoint = ""; + String accessKeyId = ""; + String accessKeySecret = ""; + String bucketName = ""; + if ( StringUtils.isNotBlank(provided.getEndpoint())){ + endpoint = provided.getEndpoint(); + }else { + endpoint = ossProperties.getEndpoint(); + } + if ( StringUtils.isNotBlank(provided.getKeyId())){ + accessKeyId = provided.getKeyId(); + }else { + accessKeyId = ossProperties.getKeyId(); + } + if ( StringUtils.isNotBlank(provided.getKeySecret())){ + accessKeySecret = provided.getKeySecret(); + }else { + accessKeySecret = ossProperties.getKeySecret(); + } + if ( StringUtils.isNotBlank(provided.getBucketName())){ + bucketName = provided.getBucketName(); + }else { + bucketName = ossProperties.getBucketName(); + } + if ( StringUtils.isBlank(module) ){ + module = ossProperties.getModule(); + } + String extension = fileName.substring(fileName.lastIndexOf(".")); + String objectName = module + "/" + UUID.randomUUID().toString() + extension; + Map resultMap = new HashMap<>(); + + // 创建OSSClient实例。 + OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); + // 创建InitiateMultipartUploadRequest对象。 + InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName); + // 初始化分片。 + InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request); + // 返回uploadId,它是分片上传事件的唯一标识。您可以根据该uploadId发起相关的操作,例如取消分片上传、查询分片上传等。 + OssPartUpload upload = new OssPartUpload(); + upload.setKey(objectName); + upload.setUploadId(upresult.getUploadId()); + return upload; + } + + /** + * 分片上传至oss + * @param upload 分片信息 + * @return + */ + public UploadPartResult uploadPart(OssPartUpload upload) { + ValidatorUtils.validateEntity(upload, DefaultGroup.class); + /** + * 获取oss的属性 + */ + String endpoint = ""; + String accessKeyId = ""; + String accessKeySecret = ""; + String bucketName = ""; + if ( StringUtils.isNotBlank(upload.getEndpoint())){ + endpoint = upload.getEndpoint(); + }else { + endpoint = ossProperties.getEndpoint(); + } + if ( StringUtils.isNotBlank(upload.getKeyId())){ + accessKeyId = upload.getKeyId(); + }else { + accessKeyId = ossProperties.getKeyId(); + } + if ( StringUtils.isNotBlank(upload.getKeySecret())){ + accessKeySecret = upload.getKeySecret(); + }else { + accessKeySecret = ossProperties.getKeySecret(); + } + if ( StringUtils.isNotBlank(upload.getBucketName())){ + bucketName = upload.getBucketName(); + }else { + bucketName = ossProperties.getBucketName(); + } + + // 创建OSSClient实例。 + OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); + + try { + UploadPartRequest uploadPartRequest = new UploadPartRequest(); + uploadPartRequest.setBucketName(bucketName); + uploadPartRequest.setKey(upload.getKey()); + uploadPartRequest.setUploadId(upload.getUploadId()); + uploadPartRequest.setInputStream(upload.getFile().getInputStream()); + // 设置分片大小。除了最后一个分片没有大小限制,其他的分片最小为100 KB。 + uploadPartRequest.setPartSize(upload.getPartSize()); + // 设置分片号。每一个上传的分片都有一个分片号,取值范围是1~10000,如果超出此范围,OSS将返回InvalidArgument错误码。 + uploadPartRequest.setPartNumber(upload.getPartNumber()); + // 每个分片不需要按顺序上传,甚至可以在不同客户端上传,OSS会按照分片号排序组成完整的文件。 + return ossClient.uploadPart(uploadPartRequest); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 获取已上传分页列表 + * @param parts + * @return + */ + public PartListing list(OssListParts parts) { + ValidatorUtils.validateEntity(parts, DefaultGroup.class); + /** + * 获取oss的属性 + */ + String endpoint = ""; + String accessKeyId = ""; + String accessKeySecret = ""; + String bucketName = ""; + if ( StringUtils.isNotBlank(parts.getEndpoint())){ + endpoint = parts.getEndpoint(); + }else { + endpoint = ossProperties.getEndpoint(); + } + if ( StringUtils.isNotBlank(parts.getKeyId())){ + accessKeyId = parts.getKeyId(); + }else { + accessKeyId = ossProperties.getKeyId(); + } + if ( StringUtils.isNotBlank(parts.getKeySecret())){ + accessKeySecret = parts.getKeySecret(); + }else { + accessKeySecret = ossProperties.getKeySecret(); + } + if ( StringUtils.isNotBlank(parts.getBucketName())){ + bucketName = parts.getBucketName(); + }else { + bucketName = ossProperties.getBucketName(); + } + + // 创建OSSClient实例。 + OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); + try { + // 列举已上传的分片。 + ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, parts.getKey(), parts.getUploadId()); + // 设置uploadId。 + //listPartsRequest.setUploadId(uploadId); + // 设置分页时每一页中分片数量为100个。默认列举1000个分片。 + listPartsRequest.setMaxParts(parts.getMaxParts()); + // 指定List的起始位置。只有分片号大于此参数值的分片会被列举。 + listPartsRequest.setPartNumberMarker(parts.getPartNumberMarker()); + return ossClient.listParts(listPartsRequest); + }catch (Exception e){ + e.printStackTrace(); + } + return null; + } + + /** + * 完成分片上传 + * @return + */ + public CompleteMultipartUploadResult completeUpload(OssComplete complete) { + ValidatorUtils.validateEntity(complete, DefaultGroup.class); + /** + * 获取oss的属性 + */ + String endpoint = ""; + String accessKeyId = ""; + String accessKeySecret = ""; + String bucketName = ""; + if ( StringUtils.isNotBlank(complete.getEndpoint())){ + endpoint = complete.getEndpoint(); + }else { + endpoint = ossProperties.getEndpoint(); + } + if ( StringUtils.isNotBlank(complete.getKeyId())){ + accessKeyId = complete.getKeyId(); + }else { + accessKeyId = ossProperties.getKeyId(); + } + if ( StringUtils.isNotBlank(complete.getKeySecret())){ + accessKeySecret = complete.getKeySecret(); + }else { + accessKeySecret = ossProperties.getKeySecret(); + } + if ( StringUtils.isNotBlank(complete.getBucketName())){ + bucketName = complete.getBucketName(); + }else { + bucketName = ossProperties.getBucketName(); + } + + // 创建OSSClient实例。 + OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); + // 在执行完成分片上传操作时,需要提供所有有效的partETags。OSS收到提交的partETags后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,OSS将把这些分片组合成一个完整的文件。 + CompleteMultipartUploadRequest completeMultipartUploadRequest = + new CompleteMultipartUploadRequest(bucketName, + complete.getKey(), + complete.getUploadId(), + complete.getTags()); + // 完成分片上传。 + return ossClient.completeMultipartUpload(completeMultipartUploadRequest); + } + + /** + * 取消oss分片上传 + * @param cancel + */ + public void abortUpload(OssCancel cancel) { + ValidatorUtils.validateEntity(cancel, DefaultGroup.class); + /** + * 获取oss的属性 + */ + String endpoint = ""; + String accessKeyId = ""; + String accessKeySecret = ""; + String bucketName = ""; + if ( StringUtils.isNotBlank(cancel.getEndpoint())){ + endpoint = cancel.getEndpoint(); + }else { + endpoint = ossProperties.getEndpoint(); + } + if ( StringUtils.isNotBlank(cancel.getKeyId())){ + accessKeyId = cancel.getKeyId(); + }else { + accessKeyId = ossProperties.getKeyId(); + } + if ( StringUtils.isNotBlank(cancel.getKeySecret())){ + accessKeySecret = cancel.getKeySecret(); + }else { + accessKeySecret = ossProperties.getKeySecret(); + } + if ( StringUtils.isNotBlank(cancel.getBucketName())){ + bucketName = cancel.getBucketName(); + }else { + bucketName = ossProperties.getBucketName(); + } + + // 创建OSSClient实例。 + OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); + // 取消分片上传。 + AbortMultipartUploadRequest abortMultipartUploadRequest = + new AbortMultipartUploadRequest(bucketName, cancel.getKey(), cancel.getUploadId()); + ossClient.abortMultipartUpload(abortMultipartUploadRequest); + } + +}