Prechádzať zdrojové kódy

完成腾讯云分块上传接口

tsurumure 4 mesiacov pred
rodič
commit
5cd8b61036

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

@@ -240,6 +240,7 @@ public class TencentCosServiceImpl implements TencentCosService {
     }
 
     // [腾讯云COS] 初始化分块上传
+    // https://cloud.tencent.com/document/product/436/65935#67d1955e-8784-4b9e-b12e-4f28f701f7eb
     @Override
     public InitiateMultipartUploadResult initiateMultipartUpload(MultipartFile multipartFile) {
 

+ 2 - 0
src/main/java/com/backendsys/modules/upload/dao/SysFileDao.java

@@ -10,5 +10,7 @@ import java.util.List;
 public interface SysFileDao extends BaseMapper<SysFile> {
 
     List<SysFile> selectUploadFileList(SysFile sysFile);
+    // 更新合并分块时的记录
+    void updateCompleteFile(SysFile sysFile);
 
 }

+ 18 - 0
src/main/java/com/backendsys/modules/upload/enums/StyleEnums.java

@@ -0,0 +1,18 @@
+package com.backendsys.modules.upload.enums;
+
+/**
+ * 样式枚举
+ */
+public enum StyleEnums {
+
+    THUMB_BACKGROUND("#f8f8f8")
+    ;
+
+    private String value;
+    public String getValue() {
+        return this.value;
+    }
+    StyleEnums(String value) {
+        this.value = value;
+    }
+}

+ 81 - 21
src/main/java/com/backendsys/modules/upload/service/impl/SysFileMultipartServiceImpl.java

@@ -1,5 +1,6 @@
 package com.backendsys.modules.upload.service.impl;
 
+import cn.hutool.core.codec.Base64;
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.io.file.FileNameUtil;
 import cn.hutool.core.util.StrUtil;
@@ -11,10 +12,12 @@ import com.backendsys.modules.system.entity.SysCommon;
 import com.backendsys.modules.system.service.SysCommonService;
 import com.backendsys.modules.upload.dao.SysFileDao;
 import com.backendsys.modules.upload.entity.SysFile;
+import com.backendsys.modules.upload.enums.StyleEnums;
 import com.backendsys.modules.upload.service.SysFileMultipartService;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.qcloud.cos.model.*;
 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;
 
@@ -29,19 +32,41 @@ import java.util.stream.Collectors;
 @Service
 public class SysFileMultipartServiceImpl implements SysFileMultipartService {
 
+    @Value("${tencent.cos.accessible-domain}")
+    private String ACCESSIBLE_DOMAIN;
     @Autowired
     private HttpRequestUtil httpRequestUtil;
     @Autowired
     private TencentCosService tencentCosService;
     @Autowired
-    private SysFileDao sysFileDao;
-    @Autowired
     private SysCommonService sysCommonService;
+    @Autowired
+    private SysFileDao sysFileDao;
 
 
-    /*
-        查一下 upload_id 多久会过期
-     */
+    // [方法] 设置缩略图 (参数)
+    // 不同的云环境 (target),缩略图配置也不一样
+    //   -1:本地:
+    //   1:腾讯云: https://cloud.tencent.com/document/product/436/113295
+    //   2:阿里云:
+    //   3:抖音云: https://www.volcengine.com/docs/6349/153626
+    private SysFile setThumbUrl(SysFile sysFile, Integer width, Integer height, String backgroundColor) {
+        // 本地上传
+        if (sysFile.getTarget() == -1) {
+            sysFile.setUrl_thumb(sysFile.getUrl() + "?w=" + width + "&h=" + height);
+        }
+        // 腾讯云 (color值通过base64加密, #f8f8f8)
+        if (sysFile.getTarget() == 1) {
+            System.out.println("base64 encode: " + Base64.encode(backgroundColor));
+            sysFile.setUrl_thumb(sysFile.getUrl() + "?imageMogr2/thumbnail/" + width + "x" + height + "/pad/1/color/" + Base64.encode(backgroundColor));
+        }
+        // 抖音云
+        if (sysFile.getTarget() == 3) {
+            sysFile.setUrl_thumb(sysFile.getUrl() + "?x-tos-process=image/resize,w_" + width + ",h_" + height + ",m_pad,color_" + backgroundColor);
+        }
+        return sysFile;
+    }
+
 
     // 1.初始化分块上传 (获得 upload_id, object_key)
     @Override
@@ -107,6 +132,7 @@ public class SysFileMultipartServiceImpl implements SysFileMultipartService {
         if (StrUtil.isEmpty(upload_id)) throw new CustException("upload_id 不能为空");
         if (upload_chunk_index == null) throw new CustException("upload_chunk_index 不能为空");
 
+
         // [Get] 获得初始化分块信息
         SysFile sysFileEntity = sysFileDao.selectOne(new LambdaQueryWrapper<SysFile>().eq(SysFile::getUpload_id, upload_id));
         if (sysFileEntity == null) throw new CustException("分块记录不存在");
@@ -120,16 +146,14 @@ public class SysFileMultipartServiceImpl implements SysFileMultipartService {
         sysCommonList.stream().forEach(sysCommon -> {
             if (sysCommon.getTag().equals("UPLOAD_TARGET")) UPLOAD_TARGET.set(Convert.toInt(sysCommon.getValue()));
         });
-
         System.out.println("[系统配置] 上传目标(-1:本地, 1:腾讯云, 2:阿里云, 3.抖音云): " + UPLOAD_TARGET);
 
+
         PartETag part_etag = null;
 
         // target: 上传目标 (-1:本地, 1:腾讯云, 2:阿里云, 3.抖音云)
         if (UPLOAD_TARGET.get() == 1) {
             UploadPartResult partResult = tencentCosService.uploadPart(multipartFile, upload_id, object_key, upload_chunk_index);
-            System.out.println("partResult:");
-            System.out.println(partResult);
             part_etag = partResult.getPartETag();
         }
 
@@ -137,7 +161,6 @@ public class SysFileMultipartServiceImpl implements SysFileMultipartService {
 //        PartListing partListing = listParts(upload_id, object_key);
 //        Integer partNumberMarker = partListing.getPartNumberMarker() + 1;
 
-
         // [Update] 更新分块文件信息
         sysFileEntity.setUpload_chunk_index(upload_chunk_index);
         sysFileDao.updateById(sysFileEntity);
@@ -165,21 +188,58 @@ public class SysFileMultipartServiceImpl implements SysFileMultipartService {
             throw new CustException("分块索引和分块数量不一致");
         }
 
-        // 查询分块集合 (etag)
-        PartListing partListing = listParts(upload_id, sysFileEntity.getObject_key());
-        List<PartSummary> partSummaryList = partListing.getParts();
-        List<PartETag> etags = partSummaryList.stream()
-            .map(partSummary -> new PartETag(partSummary.getPartNumber(), partSummary.getETag()))
-            .collect(Collectors.toList());
 
-        // 如果分块数量对不上,最好还是重新上传
-        if (sysFileEntity.getUpload_chunk_count() != etags.size()) {
-            throw new CustException("分块索引异常,请重新上传");
+        // 获得公共配置
+        List<SysCommon> sysCommonList = sysCommonService.getCommonByCategory("UPLOAD");
+        AtomicReference<Integer> UPLOAD_TARGET = new AtomicReference<>();
+        AtomicReference<Integer> UPLOAD_THUMB_SIZE = new AtomicReference<>();
+        sysCommonList.stream().forEach(sysCommon -> {
+            if (sysCommon.getTag().equals("UPLOAD_TARGET")) UPLOAD_TARGET.set(Convert.toInt(sysCommon.getValue()));
+            if (sysCommon.getTag().equals("UPLOAD_THUMB_SIZE")) UPLOAD_THUMB_SIZE.set(Convert.toInt(sysCommon.getValue()));
+        });
+        System.out.println("[系统配置] 上传目标(-1:本地, 1:腾讯云, 2:阿里云, 3.抖音云): " + UPLOAD_TARGET);
+        System.out.println("[系统配置] 图片的缩略图宽高尺寸 (px): " + UPLOAD_THUMB_SIZE);
+
+
+        // target: 上传目标 (-1:本地, 1:腾讯云, 2:阿里云, 3.抖音云)
+        if (UPLOAD_TARGET.get() == 1) {
+
+            // 查询分块集合 (etag)
+            PartListing partListing = listParts(upload_id, sysFileEntity.getObject_key());
+            List<PartSummary> partSummaryList = partListing.getParts();
+            List<PartETag> etags = partSummaryList.stream()
+                    .map(partSummary -> new PartETag(partSummary.getPartNumber(), partSummary.getETag()))
+                    .collect(Collectors.toList());
+
+            // 如果分块数量对不上,最好还是重新上传
+            if (sysFileEntity.getUpload_chunk_count() != etags.size()) {
+                throw new CustException("分块索引异常,请重新上传");
+            }
+
+            // 合并分块
+            CompleteMultipartUploadResult completeResult = tencentCosService.completeMultipartUpload(upload_id, sysFileEntity.getObject_key(), etags);
+            if (completeResult == null) throw new CustException("合并失败");
+
+            String url = ACCESSIBLE_DOMAIN + "/" + completeResult.getKey();
+            sysFileEntity.setUrl(url);
+
+            // 设置封面
+            setThumbUrl(sysFileEntity, UPLOAD_THUMB_SIZE.get(), UPLOAD_THUMB_SIZE.get(), StyleEnums.THUMB_BACKGROUND.getValue());
+
+            // [db] 更新分块记录
+            sysFileEntity.setRequest_id(completeResult.getRequestId());
+            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;
+
         }
 
-        // 合并分块
-        tencentCosService.completeMultipartUpload(upload_id, sysFileEntity.getObject_key(), etags);
-        return Map.of("upload_id", upload_id);
+        return null;
     }
 
     // 查询分块上传情况

+ 4 - 3
src/main/java/com/backendsys/modules/upload/service/impl/SysFileServiceImpl.java

@@ -15,6 +15,7 @@ import com.backendsys.modules.system.service.SysCommonService;
 import com.backendsys.modules.upload.dao.SysFileDao;
 import com.backendsys.modules.upload.entity.SysFile;
 import com.backendsys.modules.upload.entity.SysFileResult;
+import com.backendsys.modules.upload.enums.StyleEnums;
 import com.backendsys.modules.upload.service.SysFileService;
 import com.backendsys.modules.upload.utils.UploadUtil;
 import com.backendsys.utils.response.PageEntity;
@@ -88,7 +89,7 @@ public class SysFileServiceImpl extends ServiceImpl<SysFileDao, SysFile> impleme
 
         Integer UPLOAD_THUMB_SIZE = Convert.toInt(sysCommonService.getCommonByTag("UPLOAD_THUMB_SIZE"));
         sysFileList = sysFileList.stream().map(item -> {
-            setThumbUrl(item, UPLOAD_THUMB_SIZE, UPLOAD_THUMB_SIZE, "#f8f8f8");
+            setThumbUrl(item, UPLOAD_THUMB_SIZE, UPLOAD_THUMB_SIZE, StyleEnums.THUMB_BACKGROUND.getValue());
             return item;
         }).collect(Collectors.toList());
 
@@ -227,14 +228,14 @@ public class SysFileServiceImpl extends ServiceImpl<SysFileDao, SysFile> impleme
                     sysFileEntity.setUpdate_time(DateUtil.now());
                     sysFileDao.updateById(sysFileEntity);
                 }
-                sysFileEntity = setThumbUrl(sysFileEntity, UPLOAD_THUMB_SIZE.get(), UPLOAD_THUMB_SIZE.get(), "#f8f8f8");
+                sysFileEntity = setThumbUrl(sysFileEntity, UPLOAD_THUMB_SIZE.get(), UPLOAD_THUMB_SIZE.get(), StyleEnums.THUMB_BACKGROUND.getValue());
                 return sysFileEntity;
 
             } else {
                 // - 否
                 // [方法] 上传事件
                 SysFile sysFileEntity = uploadEvent(multipartFile, category_id, UPLOAD_TARGET.get());
-                sysFileEntity = setThumbUrl(sysFileEntity, UPLOAD_THUMB_SIZE.get(), UPLOAD_THUMB_SIZE.get(), "#f8f8f8");
+                sysFileEntity = setThumbUrl(sysFileEntity, UPLOAD_THUMB_SIZE.get(), UPLOAD_THUMB_SIZE.get(), StyleEnums.THUMB_BACKGROUND.getValue());
                 return sysFileEntity;
             }
 

+ 1 - 1
src/main/java/com/backendsys/utils/response/ResultEnum.java

@@ -1,7 +1,7 @@
 package com.backendsys.utils.response;
 
 /**
- * 定义API返回码枚举
+ * 定义API返回码枚举
  */
 public enum ResultEnum {
 

+ 1 - 1
src/main/resources/application-local.yml

@@ -130,7 +130,7 @@ tencent:
     # 香港
     region: ap-hongkong
     bucket-name: storage-1320301544
-    accessible-domain: http://cos.daoguyujiamcn.com
+    accessible-domain: http://cos.daoguyujia.com
 #    # 广州
 #    region: ap-guangzhou
 #    bucket-name: duanju3-1320301544

+ 1 - 1
src/main/resources/application-prod.yml

@@ -129,7 +129,7 @@ tencent:
     region: ap-hongkong
     bucket-name: storage-1320301544
     # accessible-domain: https://storage-1320301544.cos.ap-hongkong.myqcloud.com
-    accessible-domain: http://cos.daoguyujiamcn.com
+    accessible-domain: http://cos.daoguyujia.com
   ivh:
     empty-app-key: 283ca6dc9d4147debc60bf9fc3fbbe03         # 空数据账号 (我自己的子账号)
     empty-access-token: eea44503a2f64c119fb0acd2006dacb0

+ 22 - 0
src/main/resources/mapper/upload/SysFileDao.xml

@@ -72,4 +72,26 @@
         ORDER BY f.create_time DESC
     </select>
 
+    <update id="updateCompleteFile" parameterType="com.backendsys.modules.upload.entity.SysFile"
+        useGeneratedKeys="true" keyProperty="id">
+        UPDATE sys_file
+        SET upload_id = null, upload_chunk_count = null, upload_chunk_index = null
+        <if test="request_id != null and request_id != ''">, request_id = #{request_id}</if>
+        <if test="url != null and url != ''">, url = #{url}</if>
+        <if test="url_thumb != null and url_thumb != ''">, url_thumb = #{url_thumb}</if>
+        WHERE id = #{id}
+    </update>
+    <!--
+    <update id="updateAiivhMakeBroadcastAudio" parameterType="java.util.LinkedHashMap"
+        useGeneratedKeys="true" keyProperty="task_id">
+        UPDATE ai_ivh_make_broadcast_audio_task
+        SET task_status = #{task_status}
+        <if test="task_reason != null and task_reason != ''">, task_reason = #{task_reason}</if>
+        <if test="result_media_url != null and result_media_url != ''">, result_media_url = #{result_media_url}</if>
+        <if test="result_media_duration != null and result_media_duration != ''">, result_media_duration = #{result_media_duration}</if>
+        <if test="result_subitles_url != null and result_subitles_url != ''">, result_subitles_url = #{result_subitles_url}</if>
+        WHERE task_id = #{task_id}
+    </update>
+    -->
+
 </mapper>