From 456aabb893ea9aa26d6cfcbd05e67b9fb80c022d Mon Sep 17 00:00:00 2001 From: zhaojun <873019219@qq.com> Date: Sun, 5 Mar 2023 15:12:26 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E6=96=B0=E5=A2=9E=E5=A4=9A?= =?UTF-8?q?=E5=90=89=E4=BA=91=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../storage/model/enums/StorageTypeEnum.java | 3 +- .../storage/model/param/DogeCloudParam.java | 43 +++++++++ .../service/impl/DogeCloudServiceImpl.java | 91 +++++++++++++++++++ 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 src/main/java/im/zhaojun/zfile/module/storage/model/param/DogeCloudParam.java create mode 100644 src/main/java/im/zhaojun/zfile/module/storage/service/impl/DogeCloudServiceImpl.java diff --git a/src/main/java/im/zhaojun/zfile/module/storage/model/enums/StorageTypeEnum.java b/src/main/java/im/zhaojun/zfile/module/storage/model/enums/StorageTypeEnum.java index e28b63a..8e5d5c2 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/model/enums/StorageTypeEnum.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/model/enums/StorageTypeEnum.java @@ -35,7 +35,8 @@ public enum StorageTypeEnum implements IEnum { SHAREPOINT_DRIVE("sharepoint", "SharePoint"), SHAREPOINT_DRIVE_CHINA("sharepoint-china", "SharePoint 世纪互联"), GOOGLE_DRIVE("google-drive", "Google Drive"), - QINIU("qiniu", "七牛云 KODO"); + QINIU("qiniu", "七牛云 KODO"), + DOGE_CLOUD("doge-cloud", "多吉云"); private static final Map ENUM_MAP = new HashMap<>(); diff --git a/src/main/java/im/zhaojun/zfile/module/storage/model/param/DogeCloudParam.java b/src/main/java/im/zhaojun/zfile/module/storage/model/param/DogeCloudParam.java new file mode 100644 index 0000000..936c3e2 --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/module/storage/model/param/DogeCloudParam.java @@ -0,0 +1,43 @@ +package im.zhaojun.zfile.module.storage.model.param; + +import im.zhaojun.zfile.module.storage.annotation.StorageParamItem; +import im.zhaojun.zfile.module.storage.model.enums.StorageParamTypeEnum; +import lombok.Getter; +import lombok.Setter; + +/** + * @author zhaojun + */ +@Getter +@Setter +public class DogeCloudParam extends S3BaseParam { + + @StorageParamItem(name = "区域", ignoreInput = true, description = "如下拉列表中没有的区域,或想使用内网地址,可直接输入后回车,如: xxx-cn-beijing.example.com") + private String endPoint; + + @StorageParamItem(name = "存储空间名称", ignoreInput = true) + private String bucketName; + + @StorageParamItem(name = "S3AccessKey", ignoreInput = true) + private String s3AccessKey; + + @StorageParamItem(name = "S3SecretKey", ignoreInput = true) + private String s3SecretKey; + + @StorageParamItem(name = "S3SessionToken", ignoreInput = true) + private String s3SessionToken; + + @StorageParamItem(name = "存储空间名称", order = 4) + private String originBucketName; + + @StorageParamItem(name = "是否是私有空间", type = StorageParamTypeEnum.SWITCH, defaultValue = "true", description = "私有空间会生成带签名的下载链接", ignoreInput = true) + private boolean isPrivate; + + @StorageParamItem(name = "下载签名有效期", required = false, defaultValue = "1800", description = "当为私有空间时, 用于下载签名的有效期, 单位为秒, 如不配置则默认为 1800 秒.", ignoreInput = true) + private Integer tokenTime; + + @StorageParamItem(name = "是否自动配置 CORS 跨域设置", order = 100, type = StorageParamTypeEnum.SWITCH, defaultValue = "true", + description = "如不配置跨域设置,可能会无法导致无法上传,或上传后看不到文件(某些 S3 存储无需配置此选项,如 Cloudflare R2、Oracle 对象存储)", ignoreInput = true) + private boolean autoConfigCors; + +} \ No newline at end of file diff --git a/src/main/java/im/zhaojun/zfile/module/storage/service/impl/DogeCloudServiceImpl.java b/src/main/java/im/zhaojun/zfile/module/storage/service/impl/DogeCloudServiceImpl.java new file mode 100644 index 0000000..17f341b --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/module/storage/service/impl/DogeCloudServiceImpl.java @@ -0,0 +1,91 @@ +package im.zhaojun.zfile.module.storage.service.impl; + +import cn.hutool.crypto.SecureUtil; +import cn.hutool.http.Header; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpUtil; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicSessionCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import im.zhaojun.zfile.module.storage.model.enums.StorageTypeEnum; +import im.zhaojun.zfile.module.storage.model.param.DogeCloudParam; +import im.zhaojun.zfile.module.storage.service.base.AbstractS3BaseFileService; +import im.zhaojun.zfile.module.storage.service.base.RefreshTokenService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; + +/** + * @author zhaojun + */ +@Service +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +@Slf4j +public class DogeCloudServiceImpl extends AbstractS3BaseFileService implements RefreshTokenService { + + @Override + public void init() { + refreshAccessToken(); + + BasicSessionCredentials awsCredentials = new BasicSessionCredentials(param.getS3AccessKey(), param.getS3SecretKey(), param.getS3SessionToken()); + s3Client = AmazonS3ClientBuilder.standard() + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) + .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration( + param.getEndPoint(), + "automatic")) + .build(); + } + + @Override + public StorageTypeEnum getStorageTypeEnum() { + return StorageTypeEnum.DOGE_CLOUD; + } + + @Override + public void refreshAccessToken() { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("channel", "OSS_FULL"); + jsonObject.put("scopes", param.getOriginBucketName()); + + String apiDomain = "https://api.dogecloud.com"; + String apiPath = "/auth/tmp_token.json"; + + String token = getToken(apiPath, jsonObject.toJSONString()); + + HttpResponse httpResponse = HttpUtil.createPost(apiDomain + apiPath) + .body(jsonObject.toJSONString()) + .header(Header.AUTHORIZATION, "TOKEN " + param.getAccessKey() + ":" + token).execute(); + + String body = httpResponse.body(); + JSONObject resultJsonObject = JSONObject.parseObject(body); + JSONObject credentials = resultJsonObject.getJSONObject("data").getJSONObject("Credentials"); + + param.setS3AccessKey(credentials.getString("accessKeyId")); + param.setS3SecretKey(credentials.getString("secretAccessKey")); + param.setS3SessionToken(credentials.getString("sessionToken")); + + JSONArray bucketsArray = resultJsonObject.getJSONObject("data").getJSONArray("Buckets"); + if (bucketsArray == null || bucketsArray.size() == 0) { + throw new IllegalArgumentException("存储空间名称不存在"); + } + + JSONObject buckets = bucketsArray.getJSONObject(0); + + param.setBucketName(buckets.getString("s3Bucket")); + param.setEndPoint(buckets.getString("s3Endpoint")); + + + } + + + private String getToken(String apiPath, String paramsText) { + String signStr = apiPath + "\n" + paramsText; + return SecureUtil.hmacSha1(param.getSecretKey()).digestHex(signStr); + } + + +}