diff --git a/pom.xml b/pom.xml index 0abf06a55de05733354f7e017d8e2cee3665ff3d..065550a94d2d2d28e584da571e1b9c218bfb232a 100644 --- a/pom.xml +++ b/pom.xml @@ -41,6 +41,8 @@ 1.37.0 1.9.3 4.3.0 + 3.15.1 + 5.6.155 @@ -135,6 +137,18 @@ knife4j-openapi3-spring-boot-starter ${knife4j-openapi3.version} + + + com.aliyun.oss + aliyun-sdk-oss + ${aliyun.oss.version} + + + + com.qcloud + cos_api + ${tencent.cos.version} + diff --git a/springbok-common/src/main/java/cn/code4java/springbok/storage/AliyunStorage.java b/springbok-common/src/main/java/cn/code4java/springbok/storage/AliyunStorage.java new file mode 100644 index 0000000000000000000000000000000000000000..8c1816f39b71cfc4482e5302c7a520efd7864bcf --- /dev/null +++ b/springbok-common/src/main/java/cn/code4java/springbok/storage/AliyunStorage.java @@ -0,0 +1,76 @@ +package cn.code4java.springbok.storage; + +import cn.code4java.springbok.enums.OSSDistrictEnum; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.model.*; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.io.InputStream; + +/** + * @ClassName AliyunStorage + * @Description: 阿里云OSS + * @Author fengwensheng + * @Date 2024/03/11 + * @Version V1.0 + **/ +@Slf4j +@Data +public class AliyunStorage implements Storage { + + private String bucketName = "springbok"; + private String endpoint = "oss-cn-guangzhou.aliyuncs.com"; + private String accessKeyId; + private String accessKeySecret; + + @Override + public void store(InputStream inputStream, String contentType, String keyName, int type) { + OSSDistrictEnum ossDistrictEnum = OSSDistrictEnum.getOSSDistrictEnum(type); + // 创建bucket + createBucket(bucketName); + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentType(contentType); + PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossDistrictEnum.getValue() + "/" + keyName, inputStream, objectMetadata); + getOSSClient().putObject(putObjectRequest); + } + + @Override + public String generateUrl(String keyName, int type) { + OSSDistrictEnum ossDistrictEnum = OSSDistrictEnum.getOSSDistrictEnum(type); + return "https://" + bucketName + "." + endpoint + "/" + ossDistrictEnum.getValue() + "/" + keyName; + } + + /** + * 创建bucket + */ + private void createBucket(String bucketName) { + OSS ossClient = getOSSClient(); + try { + // 创建存储空间 + boolean exists = ossClient.doesBucketExist(bucketName); + if (!exists) { + CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); + // 设置存储空间读写权限为公共读,默认为私有 + createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead); + ossClient.createBucket(createBucketRequest); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (ossClient != null) { + ossClient.shutdown(); + } + } + } + + /** + * 创建OSS实例 + * + * @return + */ + private OSS getOSSClient() { + return new OSSClientBuilder().build("https://" + endpoint, accessKeyId, accessKeySecret); + } +} diff --git a/springbok-common/src/main/java/cn/code4java/springbok/storage/LocalStorage.java b/springbok-common/src/main/java/cn/code4java/springbok/storage/LocalStorage.java index f5efe520f71bc42823ddbaa21ef897929b8c8288..60b443240a6ee57d97d72337f4934e135a4f353d 100644 --- a/springbok-common/src/main/java/cn/code4java/springbok/storage/LocalStorage.java +++ b/springbok-common/src/main/java/cn/code4java/springbok/storage/LocalStorage.java @@ -1,6 +1,7 @@ package cn.code4java.springbok.storage; import cn.code4java.springbok.enums.OSSDistrictEnum; +import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.io.IOException; @@ -18,24 +19,13 @@ import java.nio.file.StandardCopyOption; * @Version V1.0 **/ @Slf4j +@Data public class LocalStorage implements Storage { private Path rootLocation; private String address; private String storagePath; - public void setStoragePath(String storagePath) { - this.storagePath = storagePath; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - @Override public void store(InputStream inputStream, String contentType, String keyName, int type) { try { diff --git a/springbok-common/src/main/java/cn/code4java/springbok/storage/TencentStorage.java b/springbok-common/src/main/java/cn/code4java/springbok/storage/TencentStorage.java new file mode 100644 index 0000000000000000000000000000000000000000..b1c6e55cd88611b09daec91287b33e68dd336df7 --- /dev/null +++ b/springbok-common/src/main/java/cn/code4java/springbok/storage/TencentStorage.java @@ -0,0 +1,93 @@ +package cn.code4java.springbok.storage; + +import cn.code4java.springbok.enums.OSSDistrictEnum; +import com.qcloud.cos.COSClient; +import com.qcloud.cos.ClientConfig; +import com.qcloud.cos.auth.BasicCOSCredentials; +import com.qcloud.cos.auth.BasicSessionCredentials; +import com.qcloud.cos.auth.COSCredentials; +import com.qcloud.cos.http.HttpProtocol; +import com.qcloud.cos.model.*; +import com.qcloud.cos.region.Region; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.io.InputStream; + +/** + * @ClassName TencentStorage + * @Description: 腾讯云COS + * @Author fengwensheng + * @Date 2024/03/12 + * @Version V1.0 + **/ +@Slf4j +@Data +public class TencentStorage implements Storage { + + private String bucketName = "springbok"; + private String endpoint = "ap-guangzhou"; + private String appId; + private String secretId; + private String secretKey; + + @Override + public void store(InputStream inputStream, String contentType, String keyName, int type) { + OSSDistrictEnum ossDistrictEnum = OSSDistrictEnum.getOSSDistrictEnum(type); + // 创建bucket + createBucket(bucketName); + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentType(contentType); + PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossDistrictEnum.getValue() + "/" + keyName, inputStream, objectMetadata); + getCOSClient().putObject(putObjectRequest); + } + + @Override + public String generateUrl(String keyName, int type) { + OSSDistrictEnum ossDistrictEnum = OSSDistrictEnum.getOSSDistrictEnum(type); + return "https://" + bucketName + ".cos." + endpoint + ".myqcloud.com/" + ossDistrictEnum.getValue() + "/" + keyName; + } + + /** + * 创建bucket + */ + private void createBucket(String bucketName) { + COSClient cosClient = getCOSClient(); + try { + // 创建存储空间 + boolean exists = cosClient.doesBucketExist(bucketName); + if (!exists) { + CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); + // 设置 bucket 的权限为 Private(私有读写), 其他可选有公有读私有写, 公有读写 + createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead); + cosClient.createBucket(createBucketRequest); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (cosClient != null) { + cosClient.shutdown(); + } + } + } + + /** + * 创建COS实例 + * + * @return + */ + private COSClient getCOSClient() { + // 1 初始化用户身份信息(secretId, secretKey)。 + COSCredentials cred = new BasicCOSCredentials(secretId, secretKey); + // 2 设置 bucket 的地域, COS 地域的简称请参见 https://cloud.tencent.com/document/product/436/6224 + // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。 + Region region = new Region(endpoint); + ClientConfig clientConfig = new ClientConfig(region); + // 这里建议设置使用 https 协议 + // 从 5.6.54 版本开始,默认使用了 https + clientConfig.setHttpProtocol(HttpProtocol.https); + // 3 生成 cos 客户端。 + COSClient cosClient = new COSClient(cred, clientConfig); + return cosClient; + } +} diff --git a/springbok-core/src/main/resources/application-dev.yml b/springbok-core/src/main/resources/application-dev.yml index 7a85ffe7171b9ef33aaafc7f1cdc679e7b3816b8..5ce4ce916612f58b7ad1001f15a0c8f5b742ba5f 100644 --- a/springbok-core/src/main/resources/application-dev.yml +++ b/springbok-core/src/main/resources/application-dev.yml @@ -101,6 +101,20 @@ springbok: storagePath: storages # 返回前端的图片地址 address: http://localhost:9988/image/ + # 阿里云OSS配置 + aliyun: + # id + accessKeyId: xxx + # secret + accessKeySecret: xxx + # 腾讯云COS配置 + tencent: + # appId + appId: xxx + # secretId + secretId: xxx + # secretKey + secretKey: xxx api: security: # 请求有效时间,单位:s diff --git a/springbok-system/src/main/java/cn/code4java/springbok/config/StorageAutoConfig.java b/springbok-system/src/main/java/cn/code4java/springbok/config/StorageAutoConfig.java index 455c28b8c6df60812d1b11444504e6a7a0532fb2..3b7332768f9a189786abb4711da0e5bfb0557c9e 100644 --- a/springbok-system/src/main/java/cn/code4java/springbok/config/StorageAutoConfig.java +++ b/springbok-system/src/main/java/cn/code4java/springbok/config/StorageAutoConfig.java @@ -1,8 +1,11 @@ package cn.code4java.springbok.config; import cn.code4java.springbok.properties.StorageProperties; +import cn.code4java.springbok.storage.AliyunStorage; import cn.code4java.springbok.storage.LocalStorage; import cn.code4java.springbok.storage.StorageService; +import cn.code4java.springbok.storage.TencentStorage; +import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -14,6 +17,7 @@ import org.springframework.context.annotation.Configuration; * @Date 2024/1/8 * @Version V1.0 **/ +@Slf4j @Configuration @EnableConfigurationProperties(StorageProperties.class) public class StorageAutoConfig { @@ -29,8 +33,13 @@ public class StorageAutoConfig { StorageService storageService = new StorageService(); String active = this.properties.getActive(); storageService.setActive(active); + log.info("当前存储模式为{}", active); if (active.equals("local")) { storageService.setStorage(localStorage()); + } else if (active.equals("aliyun")) { + storageService.setStorage(aliyunStorage()); + } else if (active.equals("tencent")) { + storageService.setStorage(tencentStorage()); } else { throw new RuntimeException("当前存储模式 " + active + " 不支持"); } @@ -46,4 +55,24 @@ public class StorageAutoConfig { localStorage.setStoragePath(local.getStoragePath()); return localStorage; } + + @Bean + public AliyunStorage aliyunStorage() { + AliyunStorage aliyunStorage = new AliyunStorage(); + StorageProperties.Aliyun aliyun = this.properties.getAliyun(); + aliyunStorage.setAccessKeyId(aliyun.getAccessKeyId()); + aliyunStorage.setAccessKeySecret(aliyun.getAccessKeySecret()); + return aliyunStorage; + } + + @Bean + public TencentStorage tencentStorage() { + TencentStorage tencentStorage = new TencentStorage(); + StorageProperties.Tencent tencent = this.properties.getTencent(); + tencentStorage.setAppId(tencent.getAppId()); + tencentStorage.setSecretId(tencent.getSecretId()); + tencentStorage.setSecretKey(tencent.getSecretKey()); + tencentStorage.setBucketName(tencentStorage.getBucketName() + "-" + tencentStorage.getAppId()); + return tencentStorage; + } } diff --git a/springbok-system/src/main/java/cn/code4java/springbok/properties/StorageProperties.java b/springbok-system/src/main/java/cn/code4java/springbok/properties/StorageProperties.java index eacfd23b7fb177d9953fec82f0440380f56174e4..0a9ed2ee102d70d52d10e465214c1ad6e5890dcf 100644 --- a/springbok-system/src/main/java/cn/code4java/springbok/properties/StorageProperties.java +++ b/springbok-system/src/main/java/cn/code4java/springbok/properties/StorageProperties.java @@ -1,5 +1,6 @@ package cn.code4java.springbok.properties; +import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; /** @@ -9,45 +10,30 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * @Date 2024/1/8 * @Version V1.0 **/ +@Data @ConfigurationProperties(prefix = "springbok.storage") public class StorageProperties { private String active; private Local local; + private Aliyun aliyun; + private Tencent tencent; - public String getActive() { - return active; - } - - public void setActive(String active) { - this.active = active; - } - - public Local getLocal() { - return local; - } - - public void setLocal(Local local) { - this.local = local; - } - + @Data public static class Local { private String address; private String storagePath; + } - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getStoragePath() { - return storagePath; - } + @Data + public static class Aliyun { + private String accessKeyId; + private String accessKeySecret; + } - public void setStoragePath(String storagePath) { - this.storagePath = storagePath; - } + @Data + public static class Tencent { + private String appId; + private String secretId; + private String secretKey; } }