Explorar el Código

Dev 分块上传

tsurumure hace 8 meses
padre
commit
f41415aa73

+ 8 - 3
src/main/java/com/backendsys/modules/sdk/tencent/cos/service/TencentCosService.java

@@ -1,12 +1,11 @@
 package com.backendsys.modules.sdk.tencent.cos.service;
 
-import com.qcloud.cos.model.InitiateMultipartUploadResult;
-import com.qcloud.cos.model.PartListing;
-import com.qcloud.cos.model.UploadResult;
+import com.qcloud.cos.model.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
 import java.net.URL;
+import java.util.List;
 import java.util.Map;
 
 public interface TencentCosService {
@@ -26,6 +25,12 @@ public interface TencentCosService {
     // [腾讯云COS] 初始化分块上传
     InitiateMultipartUploadResult initiateMultipartUpload(MultipartFile multipartFile);
 
+    // [腾讯云COS] 上传分块
+    UploadPartResult uploadPart(MultipartFile multipartFile, String upload_id, String object_key, Integer partNumber);
+
     // [腾讯云COS] 查询已上传的分块
     PartListing listParts(String upload_id, String object_key);
+
+    // [腾讯云COS] 完成分块上传
+    CompleteMultipartUploadResult completeMultipartUpload(String upload_id, String object_key, List<PartETag> partETags);
 }

+ 96 - 0
src/main/java/com/backendsys/modules/sdk/tencent/cos/service/impl/TencentCosServiceImpl.java

@@ -265,6 +265,10 @@ public class TencentCosServiceImpl implements TencentCosService {
             String object_key = "temp/" + filename;
             System.out.println("initiateMultipartUpload object: " + object_key);
 
+//            long dataSize = multipartFile.getSize();
+//            long partSize = 524288; // 512kb
+//            System.out.println("dataSize = " + dataSize + ", partSize = " + partSize);
+//            InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(BUCKET_NAME, object_key, dataSize, partSize);
             InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(BUCKET_NAME, object_key);
             InitiateMultipartUploadResult initResult = cosClient.initiateMultipartUpload(request);
             return initResult;
@@ -278,6 +282,74 @@ public class TencentCosServiceImpl implements TencentCosService {
         }
     }
 
+    // [腾讯云COS] 上传分块
+    @Override
+    public UploadPartResult uploadPart(MultipartFile multipartFile, String upload_id, String object_key, Integer partNumber) {
+        COSClient cosClient = getClient();
+        try {
+
+            // "The parameter partNumber is not valid
+            System.out.println("partNumber = " + partNumber);
+            long partSize = 524288;
+
+
+
+            // 加 partNumber 和 partSize 入参吧
+
+            UploadPartRequest uploadPartRequest = new UploadPartRequest();
+            uploadPartRequest.setBucketName(BUCKET_NAME);
+            uploadPartRequest.setKey(object_key);
+            uploadPartRequest.setUploadId(upload_id);
+            uploadPartRequest.setInputStream(multipartFile.getInputStream());
+//            uploadPartRequest.setPartSize(multipartFile.getSize());     // 设置分块的长度
+            uploadPartRequest.setPartSize(partSize);     // 设置分块的长度
+//            uploadPartRequest.setPartNumber(partNumber);                // 设置要上传的分块编号,从 1 开始
+            uploadPartRequest.setPartNumber(3);                // 设置要上传的分块编号,从 1 开始
+            return cosClient.uploadPart(uploadPartRequest);
+
+
+
+
+
+
+//            // 每个分块上传之后都会得到一个返回值 etag,保存起来用于最后合并分块时使用
+//            List<PartETag> partETags = new LinkedList<>();
+//            // 上传数据, 这里上传 10 个 1M 的分块数据
+//            for (int i = 1; i <= 10; i++) {
+//                System.out.println("i = " + i);
+//                // 这里创建一个 ByteArrayInputStream 来作为示例,实际中这里应该是您要上传的 InputStream 类型的流
+//                int inputStreamLength = 1024 * 1024;
+//                byte data[] = new byte[inputStreamLength];
+//                InputStream inputStream = new ByteArrayInputStream(data);
+//                UploadPartRequest uploadPartRequest = new UploadPartRequest();
+//                uploadPartRequest.setBucketName(BUCKET_NAME);
+//                uploadPartRequest.setKey(object_key);
+//                uploadPartRequest.setUploadId(upload_id);
+//                uploadPartRequest.setInputStream(inputStream);
+//                // 设置分块的长度
+//                uploadPartRequest.setPartSize(data.length);
+//                // 设置要上传的分块编号,从 1 开始
+//                uploadPartRequest.setPartNumber(i);
+//                try {
+//                    UploadPartResult uploadPartResult = cosClient.uploadPart(uploadPartRequest);
+//                    PartETag partETag = uploadPartResult.getPartETag();
+//                    partETags.add(partETag);
+//                } catch (CosServiceException e) {
+//                    throw e;
+//                } catch (CosClientException e) {
+//                    throw e;
+//                }
+//            }
+//            return null;
+
+
+        } catch (IOException | CosClientException e) {
+            throw new CustException(e.getMessage());
+        } finally {
+            if (cosClient != null) cosClient.shutdown();
+        }
+    }
+
 
     // [腾讯云COS] 查询已上传的分块
     @Override
@@ -300,6 +372,9 @@ public class TencentCosServiceImpl implements TencentCosService {
                     partETags.add(new PartETag(partSummary.getPartNumber(), partSummary.getETag()));
                     System.out.println("list multipart upload parts, partNum:" + partSummary.getPartNumber() + ", etag:" + partSummary.getETag());
                 }
+                System.out.println("nextPartNumberMarker: " + partListing.getNextPartNumberMarker());
+
+                listPartsRequest.setPartNumberMarker(partListing.getNextPartNumberMarker());
                 return partListing;
             } while (partListing.isTruncated());
 
@@ -308,4 +383,25 @@ public class TencentCosServiceImpl implements TencentCosService {
         }
     }
 
+
+    // [腾讯云COS] 完成分块上传
+    @Override
+    public CompleteMultipartUploadResult completeMultipartUpload(String upload_id, String object_key, List<PartETag> partETags) {
+
+        if (StrUtil.isEmpty(upload_id)) throw new CustException("upload_id 不能为空");
+        if (StrUtil.isEmpty(object_key)) throw new CustException("object_key 不能为空");
+
+        COSClient cosClient = getClient();
+        try {
+
+            // 分片上传结束后,调用 complete 完成分片上传
+            CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(BUCKET_NAME, object_key, upload_id, partETags);
+            return cosClient.completeMultipartUpload(completeMultipartUploadRequest);
+
+        } catch (CosClientException e) {
+            throw new CustException(e.getMessage());
+        } finally {
+            if (cosClient != null) cosClient.shutdown();
+        }
+    }
 }

+ 2 - 0
src/main/java/com/backendsys/modules/upload/service/SysUploadMultipartService.java

@@ -17,4 +17,6 @@ public interface SysUploadMultipartService {
     // 查询分块上传情况
     PartListing listParts(String upload_id, String object_key);
 
+    // 完成分块上传
+    Map<String, Object> completeMultipartUpload(String upload_id);
 }

+ 49 - 4
src/main/java/com/backendsys/modules/upload/service/impl/SysUploadMultipartServiceImpl.java

@@ -2,21 +2,24 @@ package com.backendsys.modules.upload.service.impl;
 
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.io.file.FileNameUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.crypto.digest.DigestUtil;
+import com.backendsys.exception.CustException;
 import com.backendsys.modules.common.config.security.utils.HttpRequestUtil;
 import com.backendsys.modules.sdk.tencent.cos.service.TencentCosService;
 import com.backendsys.modules.upload.dao.SysUploadDao;
 import com.backendsys.modules.upload.entity.SysUpload;
 import com.backendsys.modules.upload.service.SysUploadMultipartService;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.qcloud.cos.model.InitiateMultipartUploadResult;
-import com.qcloud.cos.model.PartListing;
+import com.qcloud.cos.model.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 
 @Service
@@ -58,7 +61,6 @@ public class SysUploadMultipartServiceImpl implements SysUploadMultipartService
                 sysUploadEntity.setObject_key(object_key);
                 sysUploadDao.updateById(sysUploadEntity);
             }
-
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
@@ -72,7 +74,28 @@ public class SysUploadMultipartServiceImpl implements SysUploadMultipartService
     // 上传分块
     @Override
     public Map<String, Object> uploadMultipart(MultipartFile multipartFile, String upload_id) {
-        return null;
+
+        if (StrUtil.isEmpty(upload_id)) throw new CustException("upload_id 不能为空");
+
+        SysUpload sysUploadEntity = sysUploadDao.selectOne(new LambdaQueryWrapper<SysUpload>().eq(SysUpload::getUpload_id, upload_id));
+        if (sysUploadEntity == null) throw new CustException("upload_id 不存在");
+
+        String object_key = sysUploadEntity.getObject_key();
+
+        // 查询分块上传情况 (获得下次要上传的位置)
+        PartListing partListing = listParts(upload_id, object_key);
+        Integer partNumberMarker = partListing.getPartNumberMarker() + 1;
+
+        UploadPartResult partResult = tencentCosService.uploadPart(multipartFile, upload_id, object_key, partNumberMarker);
+        System.out.println("partResult:");
+        System.out.println(partResult);
+
+        Map<String, Object> resp = new LinkedHashMap<>();
+        resp.put("upload_id", upload_id);
+        resp.put("object_key", object_key);
+        resp.put("part_number", partNumberMarker);
+        resp.put("part_etag", partResult.getPartETag());
+        return resp;
     }
 
     // 查询分块上传情况
@@ -81,4 +104,26 @@ public class SysUploadMultipartServiceImpl implements SysUploadMultipartService
         return tencentCosService.listParts(upload_id, object_key);
     }
 
+    // 完成分块上传
+    @Override
+    public Map<String, Object> completeMultipartUpload(String upload_id) {
+
+        if (StrUtil.isEmpty(upload_id)) throw new CustException("upload_id 不能为空");
+
+        SysUpload sysUploadEntity = sysUploadDao.selectOne(new LambdaQueryWrapper<SysUpload>().eq(SysUpload::getUpload_id, upload_id));
+        if (sysUploadEntity == null) throw new CustException("upload_id 不存在");
+
+        String object_key = sysUploadEntity.getObject_key();
+
+//        // 查询分块上传情况 (获得下次要上传的位置)
+//        PartListing partListing = listParts(upload_id, object_key);
+//        List<PartSummary> partSummaryList = partListing.getParts();
+//
+//        List<PartETag> partETags = new ArrayList<>();
+//
+//        tencentCosService.completeMultipartUpload(upload_id, object_key, partETags);
+
+        return Map.of("upload_id", upload_id);
+    }
+
 }