Jelajahi Sumber

完成抖音云分块上传接口

tsurumure 4 bulan lalu
induk
melakukan
4a4a6153f8

+ 3 - 1
src/main/java/com/backendsys/modules/sdk/douyincloud/tos/service/DouyinTosService.java

@@ -1,9 +1,9 @@
 package com.backendsys.modules.sdk.douyincloud.tos.service;
 
 import com.backendsys.modules.upload.entity.SysFileResult;
-import com.qcloud.cos.model.PartETag;
 import com.volcengine.tos.model.object.CompleteMultipartUploadV2Output;
 import com.volcengine.tos.model.object.CreateMultipartUploadOutput;
+import com.volcengine.tos.model.object.ListPartsOutput;
 import com.volcengine.tos.model.object.UploadPartV2Output;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -31,4 +31,6 @@ public interface DouyinTosService {
     // [抖音云TOS] 完成分块上传
     CompleteMultipartUploadV2Output completeMultipartUpload(String upload_id, String object_key);
 
+    // [抖音云TOS] 查询已上传的分块
+    List<ListPartsOutput> listParts(String upload_id, String object_key);
 }

+ 63 - 1
src/main/java/com/backendsys/modules/sdk/douyincloud/tos/service/impl/DouyinTosServiceImpl.java

@@ -30,6 +30,7 @@ import org.springframework.web.multipart.MultipartFile;
 import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.List;
 
 // 对象接口 -> 上传对象
@@ -283,7 +284,68 @@ public class DouyinTosServiceImpl implements DouyinTosService {
             CompleteMultipartUploadV2Output completedOutput = tos.completeMultipartUpload(complete);
             return completedOutput;
 
-        } catch (TosClientException | TosServerException e) {
+        } catch (TosClientException e) {
+            System.out.println("TosClientException.");
+            throw new CustException(e.getMessage());
+        } catch (TosServerException e) {
+            System.out.println("TosServerException.");
+            System.out.println("Code: " + e.getCode() + ", StatusCode: " + e.getStatusCode());
+
+            if ("EntityTooSmall".equals(e.getCode())) {
+                // 错误原因:上传的Object超出允许的最小值
+                // Your proposed upload is smaller than the minimum allowed size
+                // 分片编号从 1 开始,最大为 10000。除最后一个分片以外,其他分片大小最小为 4MiB
+            }
+            throw new CustException(e.getMessage());
+        } catch (Throwable t) {
+            throw new CustException(t.getMessage());
+        }
+
+    }
+
+
+    /**
+     * [抖音云TOS] 查询已上传的分块
+     */
+    @Override
+    public List<ListPartsOutput> listParts(String upload_id, String object_key) {
+
+        TOSV2 tos = new TOSV2ClientBuilder().build(REGION, ENDPOINT, ACCESS_KEY_ID, SECRET_ACCESS_KEY);
+        try {
+
+            List<ListPartsOutput> list = new ArrayList<>();
+            // maxParts 设置返回的记录最大条数
+            int maxParts = 1000;
+            // isTruncated 为 true 代表后续还有数据,为 false 代表已经列举完全部数据
+            boolean isTruncated = true;
+            int partNumberMarker = 0;
+            int total = 0;
+            while(isTruncated) {
+                ListPartsInput input = new ListPartsInput().setBucket(BUCKET_NAME).setKey(object_key)
+                    // 必须设置 bucket, key, uploadId
+                    .setUploadID(upload_id).setPartNumberMarker(partNumberMarker).setMaxParts(maxParts);
+                ListPartsOutput output = tos.listParts(input);
+
+                list.add(output);
+//                System.out.printf("listParts succeed, is truncated? %b, next partNumber marker is %d \n", output.isTruncated(), output.getNextPartNumberMarker());
+//                if (output.getUploadedParts() != null) {
+//                    for (int i = 0; i < output.getUploadedParts().size(); i++) {
+//                        UploadedPartV2 upload = output.getUploadedParts().get(i);
+//                        System.out.printf("Uploaded part, partNumber is %d, etag is %s, lastModified is %s, " +
+//                            "size is %d.\n", upload.getPartNumber(), upload.getEtag(), upload.getLastModified(), upload.getSize());
+//                    }
+//                    total += output.getUploadedParts().size();
+//                }
+                isTruncated = output.isTruncated();
+                partNumberMarker = output.getNextPartNumberMarker();
+            }
+            return list;
+
+        } catch (TosClientException e) {
+            System.out.println("TosClientException.");
+            throw new CustException(e.getMessage());
+        } catch (TosServerException e) {
+            System.out.println("TosServerException.");
             throw new CustException(e.getMessage());
         } catch (Throwable t) {
             throw new CustException(t.getMessage());

+ 1 - 0
src/main/java/com/backendsys/modules/sdk/tencentcloud/cos/service/TencentCosService.java

@@ -30,6 +30,7 @@ public interface TencentCosService {
     UploadPartResult uploadPart(MultipartFile multipartFile, String upload_id, String object_key, Integer partNumber);
     // [腾讯云COS] 完成分块上传
     CompleteMultipartUploadResult completeMultipartUpload(String upload_id, String object_key, List<PartETag> partETags);
+
     // [腾讯云COS] 查询已上传的分块
     PartListing listParts(String upload_id, String object_key);
 }

+ 1 - 1
src/main/java/com/backendsys/modules/upload/service/SysFileMultipartService.java

@@ -15,6 +15,6 @@ public interface SysFileMultipartService {
     Map<String, Object> multipartUploadComplete(String upload_id);
 
     // 查询分块上传情况
-    PartListing listParts(String upload_id, String object_key);
+    Map<String, Object> listParts(String upload_id, String object_key);
 
 }

+ 37 - 27
src/main/java/com/backendsys/modules/upload/service/impl/SysFileMultipartServiceImpl.java

@@ -37,7 +37,11 @@ import java.util.stream.Collectors;
 public class SysFileMultipartServiceImpl implements SysFileMultipartService {
 
     @Value("${tencent.cos.accessible-domain}")
-    private String ACCESSIBLE_DOMAIN;
+    private String TENCENT_ACCESSIBLE_DOMAIN;
+
+    @Value("${douyin.tos.domain}")
+    private String DOUYIN_ACCESSIBLE_DOMAIN;
+
     @Autowired
     private HttpRequestUtil httpRequestUtil;
     @Autowired
@@ -170,13 +174,9 @@ public class SysFileMultipartServiceImpl implements SysFileMultipartService {
         // 3: 抖音云
         if (UPLOAD_TARGET.get() == 3) {
             UploadPartV2Output partResult = douyinTosService.uploadPart(multipartFile, upload_id, object_key, upload_chunk_index);
-            part_etag = partResult.getEtag();
+            part_etag = partResult.getEtag().replace("\"", "");
         }
 
-//        // 查询分块上传情况 (获得下次要上传的位置)
-//        PartListing partListing = listParts(upload_id, object_key);
-//        Integer partNumberMarker = partListing.getPartNumberMarker() + 1;
-
         // [Update] 更新分块文件信息
         sysFileEntity.setUpload_chunk_index(upload_chunk_index);
         sysFileDao.updateById(sysFileEntity);
@@ -221,7 +221,8 @@ public class SysFileMultipartServiceImpl implements SysFileMultipartService {
         if (UPLOAD_TARGET.get() == 1) {
 
             // 查询分块集合 (etag)
-            PartListing partListing = listParts(upload_id, sysFileEntity.getObject_key());
+            Map<String, Object> partList = listParts(upload_id, sysFileEntity.getObject_key());
+            PartListing partListing = (PartListing) partList.get("listParts");
             List<PartSummary> partSummaryList = partListing.getParts();
             List<PartETag> etags = partSummaryList.stream()
                 .map(partSummary -> new PartETag(partSummary.getPartNumber(), partSummary.getETag()))
@@ -235,23 +236,8 @@ public class SysFileMultipartServiceImpl implements SysFileMultipartService {
             if (completeResult == null) throw new CustException("分块合并失败");
 
             // 拼接图片路径
-            String url = ACCESSIBLE_DOMAIN + "/" + completeResult.getKey();
-            sysFileEntity.setUrl(url);
+            sysFileEntity.setUrl(TENCENT_ACCESSIBLE_DOMAIN + "/" + completeResult.getKey());
             sysFileEntity.setRequest_id(completeResult.getRequestId());
-
-            // 设置封面
-            setThumbUrl(sysFileEntity, UPLOAD_THUMB_SIZE.get(), UPLOAD_THUMB_SIZE.get(), StyleEnums.THUMB_BACKGROUND.getValue());
-
-            // [db] 更新分块记录
-            sysFileDao.updateCompleteFile(sysFileEntity);
-
-            Map<String, Object> resp = new LinkedHashMap<>();
-            resp.put("upload_id", upload_id);
-            resp.put("request_id", completeResult.getRequestId());
-            resp.put("object_key", completeResult.getKey());
-            resp.put("url", url);
-            return resp;
-
         }
 
         // 3: 抖音云
@@ -260,17 +246,41 @@ public class SysFileMultipartServiceImpl implements SysFileMultipartService {
             CompleteMultipartUploadV2Output completeResult = douyinTosService.completeMultipartUpload(upload_id, sysFileEntity.getObject_key());
             if (completeResult == null) throw new CustException("分块合并失败");
 
-
+            // 拼接图片路径
+            sysFileEntity.setUrl(DOUYIN_ACCESSIBLE_DOMAIN + "/" + completeResult.getKey());
+            sysFileEntity.setRequest_id(completeResult.getRequestInfo().getRequestId());
 
         }
 
-        return null;
+        // 设置封面
+        setThumbUrl(sysFileEntity, UPLOAD_THUMB_SIZE.get(), UPLOAD_THUMB_SIZE.get(), StyleEnums.THUMB_BACKGROUND.getValue());
+
+        // [db] 更新分块记录
+        sysFileDao.updateCompleteFile(sysFileEntity);
+
+        Map<String, Object> resp = new LinkedHashMap<>();
+        resp.put("upload_id", upload_id);
+        resp.put("request_id", sysFileEntity.getRequest_id());
+        resp.put("object_key", sysFileEntity.getObject_key());
+        resp.put("url", sysFileEntity.getUrl());
+        return resp;
+
     }
 
     // 查询分块上传情况
     @Override
-    public PartListing listParts(String upload_id, String object_key) {
-        return tencentCosService.listParts(upload_id, object_key);
+    public Map<String, Object> listParts(String upload_id, String object_key) {
+
+        Integer UPLOAD_TARGET = Convert.toInt(sysCommonService.getCommonByTag("UPLOAD_TARGET"));
+        // target: 上传目标 (-1:本地, 1:腾讯云, 2:阿里云, 3.抖音云)
+        if (UPLOAD_TARGET == 1) {
+            return Map.of("listParts", tencentCosService.listParts(upload_id, object_key));
+        }
+        if (UPLOAD_TARGET == 3) {
+            return Map.of("listParts", douyinTosService.listParts(upload_id, object_key));
+        }
+
+        return null;
     }
 
 }