TRX 1 жил өмнө
parent
commit
f390ecfe87
20 өөрчлөгдсөн 1059 нэмэгдсэн , 0 устгасан
  1. 4 0
      FullCardClient/src/main/java/com/zhongshu/card/client/ret/ResultState.java
  2. 133 0
      FullCardClient/src/main/java/com/zhongshu/card/client/utils/type/oss/DocumentType.java
  3. 47 0
      FullCardClient/src/main/java/com/zhongshu/card/client/utils/type/oss/PlatformStoreType.java
  4. 37 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/upLoadFile/OssController.java
  5. 28 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/FileObject.java
  6. 24 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/FileTokenModel.java
  7. 33 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/ObjectStorageType.java
  8. 84 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/PlatformFileItem.java
  9. 32 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/RemoteFile.java
  10. 32 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/StsToken.java
  11. 52 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/oss/ALiObjectStorage.java
  12. 39 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/oss/HuaweiObjectStorage.java
  13. 33 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/oss/PlatformStoreObjectStorage.java
  14. 30 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/oss/SuperObjectStorage.java
  15. 29 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/oss/TencentObjectStorage.java
  16. 140 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/oss/AliObjectStorageStore.java
  17. 59 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/oss/JsonHelperOSS.java
  18. 88 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/oss/NetDiskOssService.java
  19. 93 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/oss/SuperObjectStorageStore.java
  20. 42 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/util/oss/PathAssert.java

+ 4 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/ret/ResultState.java

@@ -23,6 +23,10 @@ public enum ResultState {
     INVALID_TOKEN("无效token"),
     LOGIN_REQUIRED("需要登录"),
     CODE_ERROR("验证码错误"),
+
+    AccountNotNull("账户不能为空"),
+    AccountExists("用户存在"),
+    AccountNotExists("账户不存在"),
     ;
 
     @Getter

+ 133 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/utils/type/oss/DocumentType.java

@@ -0,0 +1,133 @@
+package com.zhongshu.card.client.utils.type.oss;
+
+public enum DocumentType {
+
+    Image(new String[]{"png", "jpg", "jpeg", "gif", "bmp"}),//图片
+    Office(new String[]{"doc", "docx", "ppt", "pptx", "xls", "xlsx", "mpp"}),//办公
+    Pdf(new String[]{"pdf"}),//pdf
+    Cad(new String[]{"dwg", "dwf", "dwt", "dx", "ifc"}),//cad
+    Video(new String[]{"mp4", "avi"}),//视频
+    Archive(new String[]{"zip", "rar"}),//压缩文件
+    Txt(new String[]{"txt", "log", "json"}),//文本类型
+    Other(new String[]{}),//其他
+
+    ;
+
+    //扩展名
+    private String[] extNames;
+
+
+    DocumentType(String[] extName) {
+        this.extNames = extName;
+    }
+
+
+    /**
+     * 转换为图片
+     *
+     * @param extName
+     * @return
+     */
+    public static String toPng(final String extName) {
+        final DocumentType documentType = findDocumentType(extName);
+        if (documentType == null) {
+            return null;
+        }
+
+        if (documentType == Image) {
+            return String.format("image", extName);
+        }
+
+        if (documentType == Cad) {
+            return String.format("cad2png", extName);
+        }
+        return null;
+    }
+
+
+    /**
+     * 转换为pdf文档
+     *
+     * @param extName
+     * @return
+     */
+    public static String toPdf(final String extName) {
+        final DocumentType documentType = findDocumentType(extName);
+        if (documentType == null) {
+            return null;
+        }
+
+        if (documentType == Office) {
+            return String.format("%s2pdf", extName);
+        }
+        return null;
+    }
+
+
+    /**
+     * 转换为文本
+     *
+     * @param extName
+     * @return
+     */
+    public static String toTxt(final String extName) {
+        final DocumentType documentType = findDocumentType(extName);
+        if (documentType == null) {
+            return null;
+        }
+
+        if (documentType == Office || documentType == Pdf) {
+            return String.format("%s2txt", extName);
+        } else if (documentType == Cad) {
+            return "cad2txt";
+        } else if (documentType == Archive) {
+            return String.format("%s2list", extName);
+        } else if (documentType == Image) {
+            return "image2txt";
+        }
+        return null;
+    }
+
+    public static String toVideo(final String extName) {
+        final DocumentType documentType = findDocumentType(extName);
+        if (documentType == null) {
+            return null;
+        }
+        if (documentType == Video) {
+            return String.format("%s2mp4", extName);
+        }
+        return null;
+    }
+
+
+    public static String toPano(final String extName) {
+        final DocumentType documentType = findDocumentType(extName);
+        if (documentType == null) {
+            return null;
+        }
+        if (documentType == Cad) {
+            return "cad2pano";
+        }
+        return null;
+    }
+
+    /**
+     * 查询文档类型
+     *
+     * @param extName
+     * @return
+     */
+    public static DocumentType findDocumentType(String extName) {
+        final String target = extName.toLowerCase();
+        for (DocumentType documentType : DocumentType.values()) {
+            for (String documentTypeExtName : documentType.extNames) {
+                if (documentTypeExtName.equals(target)) {
+                    return documentType;
+                }
+            }
+        }
+        return Other;
+    }
+
+
+}

+ 47 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/utils/type/oss/PlatformStoreType.java

@@ -0,0 +1,47 @@
+package com.zhongshu.card.client.utils.type.oss;
+
+import lombok.Getter;
+
+/**
+ * 平台存储路径常量
+ */
+public enum PlatformStoreType {
+
+
+    //所有文件都存在这一级后面
+    Store("store", "存储"),
+
+    //预览文件存储
+    PreView("preview", "预览"),
+
+    ;
+
+    PlatformStoreType(String path, String remark) {
+        this.path = path;
+        this.remark = remark;
+    }
+
+    @Getter
+    private String path;
+
+    @Getter
+    private String remark;
+
+
+    /**
+     * 通过路径查询类型
+     *
+     * @param path
+     * @return
+     */
+    public static PlatformStoreType valueOfPath(String path) {
+        for (PlatformStoreType storeType : PlatformStoreType.values()) {
+            if (storeType.getPath().equals(path)) {
+                return storeType;
+            }
+        }
+        return null;
+    }
+
+
+}

+ 37 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/upLoadFile/OssController.java

@@ -0,0 +1,37 @@
+package com.zhongshu.card.server.core.controller.upLoadFile;
+
+import com.github.microservice.auth.security.annotations.ResourceAuth;
+import com.github.microservice.auth.security.type.AuthType;
+import com.zhongshu.card.client.ret.ResultContent;
+import com.zhongshu.card.server.core.model.upLoadFile.RemoteFile;
+import com.zhongshu.card.server.core.model.upLoadFile.StsToken;
+import com.zhongshu.card.server.core.service.oss.NetDiskOssService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author TRX
+ * @date 2024/4/10
+ */
+@Validated
+@RestController
+@RequestMapping("oss")
+@Tag(name = "上传文件OSS")
+public class OssController {
+
+    @Autowired
+    NetDiskOssService netDiskOssService;
+
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "得到上传文件Token", description = "得到上传文件Token")
+    @RequestMapping(value = "getUploadToken", method = {RequestMethod.POST})
+    public ResultContent<StsToken> getUploadToken(@RequestBody RemoteFile remoteFile) {
+        return netDiskOssService.getUploadToken(remoteFile);
+    }
+}

+ 28 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/FileObject.java

@@ -0,0 +1,28 @@
+package com.zhongshu.card.server.core.model.upLoadFile;
+
+import com.zhongshu.card.client.utils.type.oss.DocumentType;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class FileObject {
+
+    //URL地址
+    private String url;
+    //文档类型
+    private DocumentType documentType;
+    //扩展名
+    private String extName;
+    //文件尺寸
+    private Long length;
+
+    private String md5;
+    private Long crc32;
+
+
+}

+ 24 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/FileTokenModel.java

@@ -0,0 +1,24 @@
+package com.zhongshu.card.server.core.model.upLoadFile;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Collection;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class FileTokenModel {
+
+    private String token;
+
+    private String ak;
+
+    //bucket
+    private String bucket;
+
+    private Collection<String> path;
+
+    private Number expiredTime;
+}

+ 33 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/ObjectStorageType.java

@@ -0,0 +1,33 @@
+package com.zhongshu.card.server.core.model.upLoadFile;
+
+import com.zhongshu.card.server.core.model.upLoadFile.oss.ALiObjectStorage;
+import com.zhongshu.card.server.core.model.upLoadFile.oss.HuaweiObjectStorage;
+import com.zhongshu.card.server.core.model.upLoadFile.oss.SuperObjectStorage;
+import com.zhongshu.card.server.core.model.upLoadFile.oss.TencentObjectStorage;
+import lombok.Getter;
+
+/**
+ * 对象存储类型
+ */
+public enum ObjectStorageType {
+
+    ALi("阿里云oss", ALiObjectStorage.class),//阿里
+    Tencent("腾讯云cos", TencentObjectStorage.class),//腾讯
+    Huawei("华为云obs", HuaweiObjectStorage.class),//华为云
+    BaiDu("百度云bos", null),//百度
+    Platform("平台os", null); //平台
+
+
+    //名称
+    private String name;
+
+    //对象存储配置对象
+    @Getter
+    private Class<? extends SuperObjectStorage> objectStorageConfigClass;
+
+
+    ObjectStorageType(String name, Class<? extends SuperObjectStorage> objectStorageConfigClass) {
+        this.name = name;
+        this.objectStorageConfigClass = objectStorageConfigClass;
+    }
+}

+ 84 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/PlatformFileItem.java

@@ -0,0 +1,84 @@
+package com.zhongshu.card.server.core.model.upLoadFile;
+
+import com.zhongshu.card.client.utils.type.oss.PlatformStoreType;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class PlatformFileItem {
+
+    private String accountId;
+    private PlatformStoreType platformStoreType;
+    private String[] sourcePath;
+    private Long versionNumber;
+
+    private Boolean isReserveName;
+    private String orgiFileName;
+
+
+    public static PlatformFileItem from(String... path) {
+        String accountName = path[0];
+        PlatformStoreType platformStoreType = PlatformStoreType.valueOfPath(path[1]);
+        String[] sourcePath = Arrays.copyOfRange(path, 2, path.length - 1);
+        Long versionNumber = 1L;
+        try {
+            versionNumber = Long.valueOf(FilenameUtils.getBaseName(path[path.length - 1]));
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return PlatformFileItem.builder().accountId(accountName).platformStoreType(platformStoreType).sourcePath(sourcePath).versionNumber(versionNumber).build();
+    }
+
+
+    /**
+     * 转换为路径 , 文件路径 /a/b/file/1.jpg ; 平台路径 /00001/store/a/b/file/1.jpg
+     *
+     * @return
+     */
+    public String[] toPath(PathType pathType) {
+        //文件名
+        final String fileName = sourcePath[sourcePath.length - 1];
+        //文件名
+        final String baseName = FilenameUtils.getName(fileName);
+        //扩展名
+        final String extName = FilenameUtils.getExtension(fileName);
+        //新的文件名,如果没有扩展名则为空字符串,有则使用原文件的扩展名
+        String newFileName = String.format("%s%s", getVersionNumber(), extName == null ? "" : "." + extName);
+        if (isReserveName != null && isReserveName && StringUtils.isNotEmpty(orgiFileName)) {
+            newFileName = orgiFileName;
+        }
+        String finalNewFileName = newFileName;
+        List<String> paths = new ArrayList<>() {{
+            if (pathType == PathType.OSS) {
+                add(getAccountId());
+                add(getPlatformStoreType().getPath());
+                addAll(List.of(Arrays.copyOfRange(sourcePath, 0, sourcePath.length - 1)));
+                add(baseName);
+                add(finalNewFileName);
+            } else if (pathType == PathType.File) {
+                addAll(List.of(Arrays.copyOfRange(sourcePath, 0, sourcePath.length - 1)));
+                add(baseName);
+                add(finalNewFileName);
+            }
+        }};
+        return paths.toArray(String[]::new);
+    }
+
+
+    public static enum PathType {
+        OSS,//对象存储
+        File //平台
+    }
+
+}

+ 32 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/RemoteFile.java

@@ -0,0 +1,32 @@
+package com.zhongshu.card.server.core.model.upLoadFile;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * 远程文件
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class RemoteFile {
+
+    //账户名
+    @Schema(description = "accountId")
+    private String accountId;
+
+    //文件路径
+    @Schema(description = "path", example = "[['other','文件.docx']]")
+    private List<String> path;
+
+    @Schema(description = "保留原名称")
+    private Boolean isReserveName = Boolean.FALSE;
+
+    private String fileName;
+
+    private List<String> fileNames;
+}

+ 32 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/StsToken.java

@@ -0,0 +1,32 @@
+package com.zhongshu.card.server.core.model.upLoadFile;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * 获取上传令牌
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class StsToken {
+    //过期时间
+    private Long expiredTime;
+    //令牌
+    private Map<String, Object> token;
+    //存储对象类型
+    private ObjectStorageType storageType;
+    //操作文件的路径
+    private Collection<String[]> paths;
+    //存储桶
+    private String bucket;
+    //端点
+    private String endPoint;
+
+}

+ 52 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/oss/ALiObjectStorage.java

@@ -0,0 +1,52 @@
+package com.zhongshu.card.server.core.model.upLoadFile.oss;
+
+import com.zhongshu.card.server.core.model.upLoadFile.ObjectStorageType;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Component
+@ConfigurationProperties(prefix = "oss")
+public class ALiObjectStorage extends SuperObjectStorage {
+
+    //Endpoint以成都为例,其它Region请按实际情况填写。
+    private String endpoint = "oss-cn-chengdu.aliyuncs.com";
+
+    //对象存储
+    private String bucket = "zlnd-dev";
+
+
+    // https://help.aliyun.com/document_detail/100624.htm 使用STS临时访问凭证访问OSS
+    // sts 临时访问凭证
+    // 1. https://ram.console.aliyun.com 创建RAM用户 , 勾选 "OpenApi 访问调用" , 获取 	AccessKeyId  & AccessKeySecret 注意 : 必须使用用户的 ak 和 sk
+    // 2. 用户添加权限 AliyunSTSAssumeRoleAccess  AliyunOSSFullAccess
+    // 3. 创建角色 , 单击复制,保存角色的ARN  acs:ram::xxxxxx:role/netdisk
+    // 4. 设置角色权限 AliyunSTSAssumeRoleAccess  AliyunOSSFullAccess
+
+    // 账户id
+    private String accessKeyId;
+
+    //密钥
+    private String accessKeySecret;
+
+    //角色id acs:ram::xxxxxx:role/netdisk
+    private String arn;
+
+    @Override
+    public ObjectStorageType storageType() {
+        return ObjectStorageType.ALi;
+    }
+
+    public String getShowEndpoint() {
+        if (StringUtils.isNotEmpty(endpoint)) {
+            return endpoint.replace(".aliyuncs.com", "");
+        }
+        return "";
+    }
+}

+ 39 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/oss/HuaweiObjectStorage.java

@@ -0,0 +1,39 @@
+package com.zhongshu.card.server.core.model.upLoadFile.oss;
+
+import com.zhongshu.card.server.core.model.upLoadFile.ObjectStorageType;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class HuaweiObjectStorage extends SuperObjectStorage {
+
+    private String endPoint;
+
+    //控制台 - 我的凭证 - 访问密钥
+    private String ak;
+
+    private String sk;
+
+    private String bucketName;
+
+
+    //创建一个委托账号 (IAM 用户)  , 用于生成安全令牌 ,
+    // 控制台 ->  统一身份认证服务 -> 创建用户
+    //账号和密码,用于创建临时令牌
+    private String userName; //创建的 IAM 用户名
+
+    //IAM的密码
+    private String passWord;
+
+    //帐号名 : 控制台 -> 我的凭证
+    private String domainName;
+
+
+    @Override
+    public ObjectStorageType storageType() {
+        return ObjectStorageType.Huawei;
+    }
+}

+ 33 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/oss/PlatformStoreObjectStorage.java

@@ -0,0 +1,33 @@
+package com.zhongshu.card.server.core.model.upLoadFile.oss;
+
+import com.zhongshu.card.server.core.model.upLoadFile.ObjectStorageType;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 平台存储
+ */
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class PlatformStoreObjectStorage extends SuperObjectStorage {
+
+    //应用
+    private String ak;
+
+    //密码
+    private String sk;
+
+    //存储桶
+    private String bucket;
+
+    //端的地址和端口
+    private String endpoint;
+
+    @Override
+    public ObjectStorageType storageType() {
+        return ObjectStorageType.Platform;
+    }
+}

+ 30 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/oss/SuperObjectStorage.java

@@ -0,0 +1,30 @@
+package com.zhongshu.card.server.core.model.upLoadFile.oss;
+
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.zhongshu.card.server.core.model.upLoadFile.ObjectStorageType;
+import lombok.Getter;
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "_type")
+@JsonSubTypes({
+        @JsonSubTypes.Type(value = ALiObjectStorage.class, name = "ALiObjectStorage"),  //阿里云
+        @JsonSubTypes.Type(value = TencentObjectStorage.class, name = "TencentObjectStorage"), //腾讯云
+        @JsonSubTypes.Type(value = HuaweiObjectStorage.class, name = "HuaweiObjectStorage"),  //阿里云
+        @JsonSubTypes.Type(value = PlatformStoreObjectStorage.class, name = "PlatformStoreObjectStorage"),
+})
+public abstract class SuperObjectStorage {
+
+    //令牌过期时间
+    @Getter
+    private int stsDurationSeconds = 3600;
+
+    /**
+     * 类型
+     *
+     * @return
+     */
+    public abstract ObjectStorageType storageType();
+
+
+}

+ 29 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/model/upLoadFile/oss/TencentObjectStorage.java

@@ -0,0 +1,29 @@
+package com.zhongshu.card.server.core.model.upLoadFile.oss;
+
+import com.zhongshu.card.server.core.model.upLoadFile.ObjectStorageType;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class TencentObjectStorage extends SuperObjectStorage {
+
+    //https://console.cloud.tencent.com/cam/capi secretId & secretKey
+    private String secretId;
+
+    private String secretKey;
+
+    //存储桶的名称 , dev-1251834475
+    private String bucket;
+
+    //区域 , ap-chengdu
+    private String region;
+
+
+    @Override
+    public ObjectStorageType storageType() {
+        return ObjectStorageType.Tencent;
+    }
+}

+ 140 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/oss/AliObjectStorageStore.java

@@ -0,0 +1,140 @@
+package com.zhongshu.card.server.core.service.oss;
+
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.aliyun.oss.model.OSSObject;
+import com.aliyun.oss.model.PutObjectRequest;
+import com.aliyun.oss.model.PutObjectResult;
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.auth.sts.AssumeRoleRequest;
+import com.aliyuncs.auth.sts.AssumeRoleResponse;
+import com.aliyuncs.http.MethodType;
+import com.aliyuncs.profile.DefaultProfile;
+import com.aliyuncs.profile.IClientProfile;
+import com.github.microservice.components.data.mongo.mongo.helper.DBHelper;
+import com.github.microservice.core.util.JsonUtil;
+import com.zhongshu.card.client.utils.type.oss.DocumentType;
+import com.zhongshu.card.server.core.model.upLoadFile.FileObject;
+import com.zhongshu.card.server.core.model.upLoadFile.ObjectStorageType;
+import com.zhongshu.card.server.core.model.upLoadFile.StsToken;
+import com.zhongshu.card.server.core.model.upLoadFile.oss.ALiObjectStorage;
+import com.zhongshu.card.server.core.model.upLoadFile.oss.SuperObjectStorage;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FilenameUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cglib.beans.BeanMap;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+
+@Slf4j
+@Component
+public class AliObjectStorageStore extends SuperObjectStorageStore {
+
+    @Autowired
+    private DBHelper dbHelper;
+
+    private ALiObjectStorage aLiObjectStorage;
+
+    //持久化oss客户端对象
+    private OSS ossClient;
+
+//    public AliObjectStorageStore(String accountName, SuperObjectStorage objectStorage) {
+//        super(accountName, objectStorage);
+//        aLiObjectStorage = (ALiObjectStorage) objectStorage;
+//        initOSSClient();
+//    }
+
+    public void setInfo(String accountName, SuperObjectStorage objectStorage) {
+        super.setInfo(accountName, objectStorage);
+        aLiObjectStorage = (ALiObjectStorage) objectStorage;
+        initOSSClient();
+    }
+
+    /**
+     * 初始化oss客户端
+     */
+    private void initOSSClient() {
+        this.ossClient = new OSSClientBuilder().build(aLiObjectStorage.getEndpoint(), aLiObjectStorage.getAccessKeyId(), aLiObjectStorage.getAccessKeySecret());
+    }
+
+
+    @Override
+    @SneakyThrows
+    public StsToken getStsToken(Collection<String[]> allowPath) {
+        //允许访问的
+        final String policy = JsonUtil.toJson(new HashMap<>() {{
+            put("version", "1");
+            put("Statement", new Object[]{new HashMap<>() {{
+                put("Action", new Object[]{"oss:PutObject"});
+                put("Effect", "Allow");
+                put("Resource", allowPath.stream().map((it) -> {
+                    return String.format("acs:oss:*:*:%s/%s", aLiObjectStorage.getBucket(), String.join("/", it));
+                }).toArray(String[]::new));
+            }}});
+        }});
+
+        String regionId = "";
+        // 添加endpoint。适用于Java SDK 3.12.0及以上版本。
+        DefaultProfile.addEndpoint(regionId, "Sts", "sts.aliyuncs.com");
+        IClientProfile profile = DefaultProfile.getProfile(regionId, this.aLiObjectStorage.getAccessKeyId(), this.aLiObjectStorage.getAccessKeySecret());
+        // 构造client。
+        DefaultAcsClient client = new DefaultAcsClient(profile);
+        final AssumeRoleRequest request = new AssumeRoleRequest();
+        // 适用于Java SDK 3.12.0及以上版本。
+        request.setSysMethod(MethodType.POST);
+        request.setRoleArn(this.aLiObjectStorage.getArn());
+        request.setRoleSessionName(String.format("%sSession", this.aLiObjectStorage.getAccessKeyId()));
+        request.setPolicy(policy); // 如果policy为空,则用户将获得该角色下所有权限。
+        request.setDurationSeconds(new BigDecimal(this.aLiObjectStorage.getStsDurationSeconds()).longValue()); // 设置临时访问凭证的有效时间为3600秒。
+        final AssumeRoleResponse response = client.getAcsResponse(request);
+        return StsToken.builder().token(BeanMap.create(response.getCredentials()))//token
+                .bucket(this.aLiObjectStorage.getBucket())//bucket
+                .paths(allowPath)//路径
+                .expiredTime(this.dbHelper.getTime() + this.aLiObjectStorage.getStsDurationSeconds() * 1000L) //expiredTime
+                .storageType(ObjectStorageType.ALi)//类型
+                .build();
+    }
+
+    @Override
+    public FileObject getFileObject(String[] path) {
+        final String objectKey = String.join("/", path);
+        final OSSObject ossObject = this.ossClient.getObject(this.aLiObjectStorage.getBucket(), objectKey);
+
+        final String url = ossObject.getResponse().getUri();
+        final String extName = FilenameUtils.getExtension(url);
+        FileObject fileObject = FileObject.builder().url(url)//url
+                .length(ossObject.getResponse().getContentLength())//length
+                .documentType(DocumentType.findDocumentType(extName))//文档类型
+                .build();
+        return fileObject;
+    }
+
+    @Override
+    public String[] uploadFileObject(String[] path, InputStream inputStream, Long length) {
+        String objectName = String.join("/", path);
+        PutObjectRequest putObjectRequest = new PutObjectRequest(this.aLiObjectStorage.getBucket(), objectName, inputStream);
+        PutObjectResult putObjectResult = this.ossClient.putObject(putObjectRequest);
+        return Arrays.stream(putObjectRequest.getKey().split("/")).filter(it -> StringUtils.hasText(it)).toArray(String[]::new);
+    }
+
+    @Override
+    public boolean deleteFileObject(String[] path) {
+        final String objectKey = String.join("/", path);
+        this.ossClient.deleteObject(this.aLiObjectStorage.getBucket(), objectKey);
+        return true;
+    }
+
+
+    @Override
+    public void destroy() {
+        log.info("destroy - {}", this);
+        this.ossClient.shutdown();
+    }
+}

+ 59 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/oss/JsonHelperOSS.java

@@ -0,0 +1,59 @@
+package com.zhongshu.card.server.core.service.oss;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+class JsonHelperOSS {
+
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+
+    /**
+     * 转换到json字符串
+     *
+     * @param object
+     * @return
+     * @throws Exception
+     */
+    public String toJson(Object object, boolean format) {
+        try {
+            if (format) {
+                return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
+            } else {
+                return objectMapper.writeValueAsString(object);
+            }
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+
+    /**
+     * 转换到json字符串
+     *
+     * @param object
+     * @return
+     */
+    public String toJson(Object object) {
+        return toJson(object, false);
+    }
+
+
+    /**
+     * 转换为对象
+     *
+     * @param json
+     * @param cls
+     * @return
+     * @throws Exception
+     */
+    public <T> T toObject(String json, Class<T> cls) throws Exception {
+        return objectMapper.readValue(json, cls);
+    }
+}

+ 88 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/oss/NetDiskOssService.java

@@ -0,0 +1,88 @@
+package com.zhongshu.card.server.core.service.oss;
+
+import com.google.common.collect.Lists;
+import com.zhongshu.card.client.ret.ResultContent;
+import com.zhongshu.card.client.ret.ResultState;
+import com.zhongshu.card.client.utils.type.oss.PlatformStoreType;
+import com.zhongshu.card.server.core.dao.org.UserCountDao;
+import com.zhongshu.card.server.core.domain.org.UserAccount;
+import com.zhongshu.card.server.core.model.upLoadFile.PlatformFileItem;
+import com.zhongshu.card.server.core.model.upLoadFile.RemoteFile;
+import com.zhongshu.card.server.core.model.upLoadFile.StsToken;
+import com.zhongshu.card.server.core.model.upLoadFile.oss.ALiObjectStorage;
+import com.zhongshu.card.server.core.service.base.SuperService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+/**
+ * @author TRX
+ * @date 2024/4/10
+ */
+@Slf4j
+@Service
+public class NetDiskOssService extends SuperService {
+
+    @Autowired
+    private AliObjectStorageStore aliObjectStorageStore;
+
+    @Autowired
+    ALiObjectStorage aLiObjectStorage;
+
+    @Autowired
+    UserCountDao userCountDao;
+
+    public ResultContent<StsToken> getUploadToken(RemoteFile remoteFile) {
+//        PathAssert.validate(remoteFile.getPath());
+        String userId = getCurrentUserId();
+        UserAccount user = userCountDao.findTopByUserId(userId);
+        if (user == null) {
+            return ResultContent.build(ResultState.AccountNotExists);
+        }
+        Boolean isReserveName = remoteFile.getIsReserveName();
+        String fileName = remoteFile.getFileName();
+        aliObjectStorageStore.setInfo(user.getId(), aLiObjectStorage);
+        List<String[]> allPaths = buildPathByUser(remoteFile, user);
+
+        // 获取三方持久化对象
+//        final SuperObjectStorageStore objectStorageStore = this.objectStorageStore.getObjectStorageStore(account.getId());
+        Collection<String[]> paths = allPaths.parallelStream().map((path) -> {
+            return this.toPlatformFileStoreObjectPath(user, path, isReserveName, fileName);
+        }).collect(Collectors.toList());
+        StsToken stsToken = aliObjectStorageStore.getStsToken(paths);
+        stsToken.setEndPoint(aLiObjectStorage.getShowEndpoint());
+
+        //获取操作文件路径
+        return ResultContent.buildContent(stsToken);
+    }
+
+    private String[] toPlatformFileStoreObjectPath(final UserAccount account, String[] path, Boolean isReserveName, String fileName) {
+        return buildUploadFilePathFromLatestVersion(account, path, isReserveName, fileName);
+    }
+
+    public String[] buildUploadFilePathFromLatestVersion(final UserAccount account, String[] sourcePath, Boolean isReserveName, String fileName) {
+        //文件版本号
+        final Long fileVersionNumber = 1L;
+        return PlatformFileItem.builder().accountId(account.getId()) //账户
+                .versionNumber(fileVersionNumber)//版本
+                .platformStoreType(PlatformStoreType.Store) //类型
+                .sourcePath(sourcePath)//原路径
+                .isReserveName(isReserveName).orgiFileName(fileName).build().toPath(PlatformFileItem.PathType.OSS);
+    }
+
+    public List<String[]> buildPathByUser(RemoteFile param, UserAccount user) {
+        List<String[]> paths = new ArrayList<>();
+        param.getFileNames().forEach(it -> {
+            String[] split = it.split("\\.");
+            List<String> path = Lists.newArrayList(new String[]{user.getId(), UUID.randomUUID().toString() + "." + split[1]});
+            paths.add(path.toArray(new String[0]));
+        });
+        return paths;
+    }
+}

+ 93 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/oss/SuperObjectStorageStore.java

@@ -0,0 +1,93 @@
+package com.zhongshu.card.server.core.service.oss;
+
+import com.zhongshu.card.server.core.model.upLoadFile.FileObject;
+import com.zhongshu.card.server.core.model.upLoadFile.ObjectStorageType;
+import com.zhongshu.card.server.core.model.upLoadFile.StsToken;
+import com.zhongshu.card.server.core.model.upLoadFile.oss.SuperObjectStorage;
+
+import java.io.InputStream;
+import java.util.Collection;
+
+/**
+ * 对象存储
+ */
+public abstract class SuperObjectStorageStore {
+
+    //账户名
+    private String accountName;
+    //配置信息
+    private SuperObjectStorage objectStorage;
+
+//    /**
+//     * 实例化
+//     */
+//    public SuperObjectStorageStore(String accountName, SuperObjectStorage objectStorage) {
+//        this.accountName = accountName;
+//        this.objectStorage = objectStorage;
+//    }
+
+    public void setInfo(String accountName, SuperObjectStorage objectStorage) {
+        this.accountName = accountName;
+        this.objectStorage = objectStorage;
+    }
+
+
+    /**
+     * 取出对象存储类型
+     *
+     * @return
+     */
+    public ObjectStorageType storageType() {
+        return objectStorage.storageType();
+    }
+
+
+    /**
+     * 获取临时密钥
+     *
+     * @return
+     */
+    public abstract StsToken getStsToken(Collection<String[]> path);
+
+
+    /**
+     * 如果文件存在,则获取对象链接
+     *
+     * @param path
+     * @return
+     */
+    public abstract FileObject getFileObject(String[] path);
+
+
+    /**
+     * 上传文件对象
+     *
+     * @param path
+     * @param inputStream
+     */
+    public abstract String[] uploadFileObject(String[] path, InputStream inputStream, Long length);
+
+
+    /**
+     * 删除文件对象
+     *
+     * @return
+     */
+    public abstract boolean deleteFileObject(String[] path);
+
+
+    /**
+     * 释放
+     */
+    public abstract void destroy();
+
+
+    protected String getAccountName() {
+        return accountName;
+    }
+
+    protected SuperObjectStorage getObjectStorage() {
+        return objectStorage;
+    }
+
+}

+ 42 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/util/oss/PathAssert.java

@@ -0,0 +1,42 @@
+package com.zhongshu.card.server.core.util.oss;
+
+import org.springframework.util.Assert;
+
+import java.util.Collection;
+
+/**
+ * 校验路径的合法性
+ */
+public class PathAssert {
+    private final static String Regex = "^[^\\/:*?\"\"<>|\\\\]+$";
+
+
+    /**
+     * 校验文件路径
+     *
+     * @param paths
+     */
+    public static void validate(String... paths) {
+        for (String path : paths) {
+            Assert.state(isValidPath(path), "文件名不合法");
+        }
+    }
+
+    /**
+     * 校验文件路径
+     *
+     * @param paths
+     */
+    public static void validate(Collection<String[]> paths) {
+        for (String[] path : paths) {
+            validate(path);
+        }
+    }
+
+
+    private static boolean isValidPath(String path) {
+        return path.matches(Regex);
+    }
+
+
+}