Browse Source

文件服务支持腾讯云

yzc 1 year ago
parent
commit
6ea5959c85

+ 13 - 0
hx-file/pom.xml

@@ -44,6 +44,19 @@
             <scope>test</scope>
         </dependency>
 
+        <!--腾讯COS对象存储SDK-->
+        <dependency>
+            <groupId>com.qcloud</groupId>
+            <artifactId>cos_api</artifactId>
+            <version>5.6.155</version>
+        </dependency>
+        <!--腾讯COS对象存储SDK依赖-->
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>1.10</version>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 35 - 0
hx-file/src/main/java/com/fjhx/file/controller/FileInfoOpenController.java

@@ -0,0 +1,35 @@
+package com.fjhx.file.controller;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.fjhx.file.entity.UploadBodyDto;
+import com.fjhx.file.service.FileInfoService;
+import com.ruoyi.common.constant.BaseSourceConstant;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * <p>
+ * 文件上传 前端控制器
+ * </p>
+ *
+ * @author yzc
+ * @since 2024/1/25
+ */
+@DS(BaseSourceConstant.BASE)
+@RestController
+@RequestMapping("/open/fileInfo")
+public class FileInfoOpenController {
+
+    @Autowired
+    private FileInfoService fileInfoService;
+
+    @PostMapping("/upload")
+    public void upload( UploadBodyDto uploadBody) {
+        fileInfoService.upload(uploadBody);
+    }
+
+}

+ 12 - 0
hx-file/src/main/java/com/fjhx/file/entity/UploadBodyDto.java

@@ -0,0 +1,12 @@
+package com.fjhx.file.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.web.multipart.MultipartFile;
+
+@Getter
+@Setter
+public class UploadBodyDto {
+    private String key;
+    private MultipartFile file;
+}

+ 5 - 0
hx-file/src/main/java/com/fjhx/file/service/FileInfoService.java

@@ -22,6 +22,11 @@ public interface FileInfoService extends BaseService<FileInfo> {
     SingVo getSing(SingDto dto);
 
     /**
+     * 后端上传地址
+     */
+    void upload(UploadBodyDto uploadBody);
+
+    /**
      * 文件表列表
      */
     Map<Long, List<FileInfoVo>> getList(FileInfoSelectDto dto);

+ 73 - 12
hx-file/src/main/java/com/fjhx/file/service/impl/FileInfoServiceImpl.java

@@ -7,18 +7,19 @@ import cn.hutool.core.io.IoUtil;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.dynamic.datasource.annotation.DS;
-import com.baomidou.mybatisplus.core.toolkit.IdWorker;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fjhx.file.entity.*;
 import com.fjhx.file.mapper.FileInfoMapper;
 import com.fjhx.file.service.FileInfoService;
+import com.fjhx.file.utils.TencentCosUtils;
 import com.obs.services.ObsClient;
 import com.obs.services.model.PostSignatureRequest;
 import com.obs.services.model.PostSignatureResponse;
+import com.obs.services.model.PutObjectRequest;
 import com.ruoyi.common.constant.BaseSourceConstant;
 import com.ruoyi.common.core.domain.BaseIdPo;
 import com.ruoyi.common.exception.ServiceException;
@@ -26,8 +27,9 @@ import com.ruoyi.common.utils.wrapper.IWrapper;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
-import java.io.File;
+import java.io.IOException;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -54,6 +56,12 @@ public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> i
     @Value("${obs.url}")
     private String url;
 
+    @Value("${obs.type:}")
+    private String type;
+
+    @Value("${obs.uploadMethod:}")
+    private String uploadMethod;
+
     @Value("${obs.bucketName}")
     private String bucketName;
 
@@ -84,6 +92,30 @@ public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> i
                 .add(IdUtil.fastSimpleUUID() + (ObjectUtil.isEmpty(suffix) ? "" : "." + suffix))
                 .toString();
 
+        //后端上传方式
+        if (Objects.equals(uploadMethod, "back")) {
+            // 封装签名
+            Map<String, String> body = new LinkedHashMap<>();
+            body.put("key", objectKey);
+            singVo.setUploadBody(body);
+
+            // 保存文件
+            FileInfo fileInfo = new FileInfo();
+            fileInfo.setFileUrl(objectKey);
+            fileInfo.setFileName(dto.getFileName());
+            save(fileInfo);
+
+            // 封装文件信息
+            singVo.setUploadUrl("/open/fileInfo/upload");
+            singVo.setId(fileInfo.getId());
+            singVo.setFileName(dto.getFileName());
+            singVo.setFileUrl(url + objectKey);
+
+            return singVo;
+        }
+
+
+        //原华为云前端直传(默认)
         ObsClient obsClient = null;
 
         try {
@@ -123,6 +155,34 @@ public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> i
         return singVo;
     }
 
+    @Override
+    public void upload(UploadBodyDto uploadBody) {
+        MultipartFile file = uploadBody.getFile();
+        String objectKey = uploadBody.getKey();
+
+
+        //腾讯云COS对象存储
+        if (Objects.equals(type, "tencent")) {
+            TencentCosUtils.uploadFile(ak, sk, bucketName, objectKey, file);
+        }
+        //华为云OBS对象存储(默认)
+        else if (Objects.equals(type, "huawei")) {
+            ObsClient obsClient = getObsClient();
+            try {
+                PutObjectRequest putObjectRequest = new PutObjectRequest();
+                putObjectRequest.setBucketName(bucketName);
+                putObjectRequest.setObjectKey(objectKey);
+                putObjectRequest.setInput(file.getInputStream());
+                obsClient.putObject(putObjectRequest);
+            } catch (IOException e) {
+                log.error(e.getMessage(), e);
+                throw new ServiceException("华为云 文件上传失败!");
+            } finally {
+                IoUtil.close(obsClient);
+            }
+        }
+    }
+
     @DS(BaseSourceConstant.BASE)
     @Override
     public Map<Long, List<FileInfoVo>> getList(FileInfoSelectDto dto) {
@@ -169,6 +229,7 @@ public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> i
 
     /**
      * 保存文件--直接插入
+     *
      * @param obsFileList  文件列表
      * @param businessId   业务id
      * @param businessType 业务文件类型
@@ -189,7 +250,6 @@ public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> i
     }
 
     /**
-     *
      * @param obsFileList  文件列表
      * @param businessId   业务id
      * @param businessType 业务文件类型
@@ -238,22 +298,23 @@ public class FileInfoServiceImpl extends ServiceImpl<FileInfoMapper, FileInfo> i
 
     /**
      * 交换业务ID
-     * @param  oldBusinessId 旧业务id
-     * @param  newBusinessId 新业务id
+     *
+     * @param oldBusinessId 旧业务id
+     * @param newBusinessId 新业务id
      */
     @DS(BaseSourceConstant.BASE)
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void exchangeBusinessId(Long oldBusinessId, Long newBusinessId) {
-        List<FileInfo> oldFile = this.list(Wrappers.<FileInfo>query().lambda().select(FileInfo::getId).eq(FileInfo::getBusinessId,oldBusinessId));
-        List<FileInfo> newFile = this.list(Wrappers.<FileInfo>query().lambda().select(FileInfo::getId).eq(FileInfo::getBusinessId,newBusinessId));
-        if(CollectionUtils.isNotEmpty(oldFile)){
+        List<FileInfo> oldFile = this.list(Wrappers.<FileInfo>query().lambda().select(FileInfo::getId).eq(FileInfo::getBusinessId, oldBusinessId));
+        List<FileInfo> newFile = this.list(Wrappers.<FileInfo>query().lambda().select(FileInfo::getId).eq(FileInfo::getBusinessId, newBusinessId));
+        if (CollectionUtils.isNotEmpty(oldFile)) {
             List<Long> ids = oldFile.stream().map(FileInfo::getId).collect(Collectors.toList());
-            this.update(Wrappers.<FileInfo>update().lambda().set(FileInfo::getBusinessId,newBusinessId).in(FileInfo::getId,ids));
+            this.update(Wrappers.<FileInfo>update().lambda().set(FileInfo::getBusinessId, newBusinessId).in(FileInfo::getId, ids));
         }
-        if(CollectionUtils.isNotEmpty(newFile)){
+        if (CollectionUtils.isNotEmpty(newFile)) {
             List<Long> ids = newFile.stream().map(FileInfo::getId).collect(Collectors.toList());
-            this.update(Wrappers.<FileInfo>update().lambda().set(FileInfo::getBusinessId,oldBusinessId).in(FileInfo::getId,ids));
+            this.update(Wrappers.<FileInfo>update().lambda().set(FileInfo::getBusinessId, oldBusinessId).in(FileInfo::getId, ids));
         }
     }
 

+ 40 - 0
hx-file/src/main/java/com/fjhx/file/utils/TencentCosUtils.java

@@ -0,0 +1,40 @@
+package com.fjhx.file.utils;
+
+import com.qcloud.cos.COSClient;
+import com.qcloud.cos.ClientConfig;
+import com.qcloud.cos.auth.BasicCOSCredentials;
+import com.qcloud.cos.auth.COSCredentials;
+import com.qcloud.cos.http.HttpProtocol;
+import com.qcloud.cos.model.ObjectMetadata;
+import com.qcloud.cos.model.PutObjectRequest;
+import com.qcloud.cos.region.Region;
+import com.qcloud.cos.transfer.TransferManager;
+import com.qcloud.cos.transfer.Upload;
+import com.ruoyi.common.exception.ServiceException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.multipart.MultipartFile;
+
+@Slf4j
+public class TencentCosUtils {
+
+    public static void uploadFile(String secretId, String secretKey, String bucketName, String objectKey, MultipartFile file) {
+        COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
+        Region region = new Region("ap-shanghai");
+        ClientConfig clientConfig = new ClientConfig(region);
+        clientConfig.setHttpProtocol(HttpProtocol.https);
+        COSClient cosClient = new COSClient(cred, clientConfig);
+        TransferManager transferManager = new TransferManager(cosClient);
+        try {
+            ObjectMetadata objectMetadata = new ObjectMetadata();
+            objectMetadata.setContentLength(file.getSize());
+            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectKey, file.getInputStream(), objectMetadata);
+            Upload upload = transferManager.upload(putObjectRequest);
+            upload.waitForUploadResult();
+        } catch (Exception e) {
+            log.error("腾讯云COS对象存储上传异常" + e.getMessage());
+            throw new ServiceException("腾讯云 文件上传失败!");
+        } finally {
+            transferManager.shutdownNow(true);
+        }
+    }
+}

+ 3 - 0
ruoyi-admin/src/main/resources/application.yml

@@ -184,6 +184,9 @@ xss:
 
 
 obs:
+  # type: huawei / tencent
+  # uploadMethod: 前端直传front 后端上传back
+  # 腾讯云 ak对应secretId,sk对应secretKey
   ak: 9HNBVBHO7F3GLUCGTK5C
   sk: ZowLEoMJrICA9tOyln0yWVm0xGSiupe0gnbsZimk
   endPoint: obs.cn-south-1.myhuaweicloud.com