diff --git a/yshop-admin/src/main/resources/config/application-dev.yml b/yshop-admin/src/main/resources/config/application-dev.yml
index f6abea01..4f1ff89d 100644
--- a/yshop-admin/src/main/resources/config/application-dev.yml
+++ b/yshop-admin/src/main/resources/config/application-dev.yml
@@ -98,3 +98,13 @@ file:
avatarMaxSize: 5
+#oss配置
+oss:
+ endpoint: http://oss-cn-shenzhen.aliyuncs.com
+ custom-domain: https://xxxxx/%s
+ access-key: xxxxx
+ secret-key: xxxxx
+ bucket-name: xxxxx
+ defaultName: xxxxx
+
+
diff --git a/yshop-admin/src/main/resources/config/application-docker.yml b/yshop-admin/src/main/resources/config/application-docker.yml
index 2e415537..9a603115 100644
--- a/yshop-admin/src/main/resources/config/application-docker.yml
+++ b/yshop-admin/src/main/resources/config/application-docker.yml
@@ -104,3 +104,11 @@ file:
maxSize: 100
avatarMaxSize: 5
+#oss配置
+oss:
+ endpoint: http://oss-cn-shenzhen.aliyuncs.com
+ custom-domain: https://xxxxx//%s
+ access-key: xxxxx
+ secret-key: xxxxx
+ bucket-name: xxxxx
+ defaultName: xxxxx
diff --git a/yshop-admin/src/main/resources/config/application-prod.yml b/yshop-admin/src/main/resources/config/application-prod.yml
index b4219165..ab021307 100644
--- a/yshop-admin/src/main/resources/config/application-prod.yml
+++ b/yshop-admin/src/main/resources/config/application-prod.yml
@@ -104,3 +104,12 @@ file:
maxSize: 100
avatarMaxSize: 5
+#oss配置
+oss:
+ endpoint: http://oss-cn-shenzhen.aliyuncs.com
+ custom-domain: https://xxxxx//%s
+ access-key: xxxxx
+ secret-key: xxxxx
+ bucket-name: xxxxx
+ defaultName: xxxxx
+
diff --git a/yshop-app/src/main/resources/config/application-dev.yml b/yshop-app/src/main/resources/config/application-dev.yml
index 12ad74ee..f7577c9a 100644
--- a/yshop-app/src/main/resources/config/application-dev.yml
+++ b/yshop-app/src/main/resources/config/application-dev.yml
@@ -90,4 +90,13 @@ file:
avatarMaxSize: 5
+#oss配置
+oss:
+ endpoint: http://oss-cn-shenzhen.aliyuncs.com
+ custom-domain: https://xxxxx//%s
+ access-key: xxxxx
+ secret-key: xxxxx
+ bucket-name: xxxxx
+ defaultName: xxxxx
+
diff --git a/yshop-app/src/main/resources/config/application-docker.yml b/yshop-app/src/main/resources/config/application-docker.yml
index 729df76e..04b2163f 100644
--- a/yshop-app/src/main/resources/config/application-docker.yml
+++ b/yshop-app/src/main/resources/config/application-docker.yml
@@ -96,4 +96,11 @@ file:
maxSize: 100
avatarMaxSize: 5
-
+#oss配置
+oss:
+ endpoint: http://oss-cn-shenzhen.aliyuncs.com
+ custom-domain: https://xxxxx//%s
+ access-key: xxxxx
+ secret-key: xxxxx
+ bucket-name: xxxxx
+ defaultName: xxxxx
diff --git a/yshop-app/src/main/resources/config/application-prod.yml b/yshop-app/src/main/resources/config/application-prod.yml
index fd1f6149..0e3e23f1 100644
--- a/yshop-app/src/main/resources/config/application-prod.yml
+++ b/yshop-app/src/main/resources/config/application-prod.yml
@@ -97,3 +97,11 @@ file:
avatarMaxSize: 5
+#oss配置
+oss:
+ endpoint: http://oss-cn-shenzhen.aliyuncs.com
+ custom-domain: https://xxxxx//%s
+ access-key: xxxxx
+ secret-key: xxxxx
+ bucket-name: xxxxx
+ defaultName: xxxxx
diff --git a/yshop-mall/src/main/java/co/yixiang/modules/user/service/dto/PromUserDto.java b/yshop-mall/src/main/java/co/yixiang/modules/user/service/dto/PromUserDto.java
index 5b4c691a..110ce594 100644
--- a/yshop-mall/src/main/java/co/yixiang/modules/user/service/dto/PromUserDto.java
+++ b/yshop-mall/src/main/java/co/yixiang/modules/user/service/dto/PromUserDto.java
@@ -2,6 +2,8 @@ package co.yixiang.modules.user.service.dto;
import lombok.Data;
+import java.math.BigDecimal;
+
/**
* @ClassName PromUserDto
* @Author hupeng <610796224@qq.com>
@@ -12,7 +14,7 @@ public class PromUserDto {
private String avatar;
private String nickname;
private Integer childCount;
- private Integer numberCount;
+ private BigDecimal numberCount;
private Integer orderCount;
private Integer uid;
private String time;
diff --git a/yshop-oss/pom.xml b/yshop-oss/pom.xml
new file mode 100644
index 00000000..a21d544a
--- /dev/null
+++ b/yshop-oss/pom.xml
@@ -0,0 +1,37 @@
+
+
+
+ yshop
+ co.yixiang
+ 3.3
+
+ 4.0.0
+
+ yshop-oss
+ oss模块
+ jar
+
+ 8
+ 8
+ UTF-8
+
+
+
+ com.amazonaws
+ aws-java-sdk-s3
+ 1.11.543
+
+
+ co.yixiang
+ yshop-common
+ 2.3
+
+
+ cn.hutool
+ hutool-all
+ ${hutool.version}
+
+
+
diff --git a/yshop-oss/src/main/java/co/yixiang/oss/config/OssAutoConfiguration.java b/yshop-oss/src/main/java/co/yixiang/oss/config/OssAutoConfiguration.java
new file mode 100644
index 00000000..7f64affc
--- /dev/null
+++ b/yshop-oss/src/main/java/co/yixiang/oss/config/OssAutoConfiguration.java
@@ -0,0 +1,27 @@
+package co.yixiang.oss.config;
+
+import co.yixiang.oss.service.OssTemplate;
+import lombok.AllArgsConstructor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * aws 自动配置类
+ *
+ */
+@AllArgsConstructor
+@EnableConfigurationProperties({ OssProperties.class })
+public class OssAutoConfiguration {
+
+ private final OssProperties properties;
+
+ @Bean
+ @ConditionalOnMissingBean(OssTemplate.class)
+ @ConditionalOnProperty(name = "oss.enable", havingValue = "true", matchIfMissing = true)
+ public OssTemplate ossTemplate() {
+ return new OssTemplate(properties);
+ }
+
+}
diff --git a/yshop-oss/src/main/java/co/yixiang/oss/config/OssProperties.java b/yshop-oss/src/main/java/co/yixiang/oss/config/OssProperties.java
new file mode 100644
index 00000000..8d5e8f3b
--- /dev/null
+++ b/yshop-oss/src/main/java/co/yixiang/oss/config/OssProperties.java
@@ -0,0 +1,70 @@
+package co.yixiang.oss.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * aws 配置信息
+ *
+ * @descirption 配置文件添加: oss: enable: true endpoint: http://127.0.0.1:9000 #
+ * pathStyleAccess 采用nginx反向代理或者AWS S3 配置成true,支持第三方云存储配置成false pathStyleAccess: false
+ * access-key: bug secret-key: bug bucket-name: bug region: custom-domain:
+ * https://oss.xxx.com/,
+ *
+ * bucket 设置公共读权限
+ */
+@Data
+@ConfigurationProperties(prefix = "oss")
+public class OssProperties {
+
+ /**
+ * 对象存储服务的URL
+ */
+ private String endpoint;
+
+ /**
+ * 自定义域名
+ */
+ private String customDomain;
+
+ /**
+ * true path-style nginx 反向代理和S3默认支持 pathStyle {http://endpoint/bucketname}
+ * false supports virtual-hosted-style 阿里云等需要配置为 virtual-hosted-style
+ * 模式{http://bucketname.endpoint}
+ */
+ private Boolean pathStyleAccess = false;
+
+ /**
+ * 应用ID
+ */
+ private String appId;
+
+ /**
+ * 区域
+ */
+ private String region;
+
+ /**
+ * Access key就像用户ID,可以唯一标识你的账户
+ */
+ private String accessKey;
+
+ /**
+ * Secret key是你账户的密码
+ */
+ private String secretKey;
+
+ /**
+ * 默认的存储桶名称
+ */
+ private String bucketName ;
+
+ /**
+ * 最大线程数,默认: 100
+ */
+ private Integer maxConnections = 100;
+
+
+ private String defaultName ;
+
+}
diff --git a/yshop-oss/src/main/java/co/yixiang/oss/service/OssTemplate.java b/yshop-oss/src/main/java/co/yixiang/oss/service/OssTemplate.java
new file mode 100644
index 00000000..d4f32d09
--- /dev/null
+++ b/yshop-oss/src/main/java/co/yixiang/oss/service/OssTemplate.java
@@ -0,0 +1,252 @@
+package co.yixiang.oss.service;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import com.amazonaws.ClientConfiguration;
+import com.amazonaws.Protocol;
+import com.amazonaws.auth.AWSCredentials;
+import com.amazonaws.auth.AWSCredentialsProvider;
+import com.amazonaws.auth.AWSStaticCredentialsProvider;
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.client.builder.AwsClientBuilder;
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.AmazonS3Client;
+import com.amazonaws.services.s3.model.*;
+import com.amazonaws.util.IOUtils;
+import co.yixiang.oss.config.OssProperties;
+import lombok.Cleanup;
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import org.springframework.beans.factory.InitializingBean;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * aws-s3 通用存储操作 支持所有兼容s3协议的云存储: {阿里云OSS,腾讯云COS,七牛云,京东云,minio 等}
+ *
+ * @date 2023/5/23 6:36 上午
+ * @since 1.0
+ */
+@RequiredArgsConstructor
+public class OssTemplate implements InitializingBean {
+
+ private final OssProperties ossProperties;
+ private AmazonS3 amazonS3;
+
+ /**
+ * 创建bucket
+ * @param bucketName bucket名称
+ */
+ @SneakyThrows
+ public void createBucket(String bucketName) {
+ if (!amazonS3.doesBucketExistV2(bucketName)) {
+ amazonS3.createBucket((bucketName));
+ }
+ }
+
+ /**
+ * 获取全部bucket
+ *
+ *
+ * @see AWS
+ * API Documentation
+ */
+ @SneakyThrows
+ public List getAllBuckets() {
+ return amazonS3.listBuckets();
+ }
+
+ /**
+ * @param bucketName bucket名称
+ * @see AWS
+ * API Documentation
+ */
+ @SneakyThrows
+ public Optional getBucket(String bucketName) {
+ return amazonS3.listBuckets().stream().filter(b -> b.getName().equals(bucketName)).findFirst();
+ }
+
+ /**
+ * @param bucketName bucket名称
+ * @see AWS API
+ * Documentation
+ */
+ @SneakyThrows
+ public void removeBucket(String bucketName) {
+ amazonS3.deleteBucket(bucketName);
+ }
+
+ /**
+ * 根据文件前置查询文件
+ * @param bucketName bucket名称
+ * @param prefix 前缀
+ * @param recursive 是否递归查询
+ * @return S3ObjectSummary 列表
+ * @see AWS
+ * API Documentation
+ */
+ @SneakyThrows
+ public List getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
+ ObjectListing objectListing = amazonS3.listObjects(bucketName, prefix);
+ return new ArrayList<>(objectListing.getObjectSummaries());
+ }
+
+ /**
+ * 获取文件外链
+ * @param objectName 文件名称
+ * @return url
+ * @see AmazonS3#generatePresignedUrl(String bucketName, String key, Date expiration)
+ */
+ @SneakyThrows
+ public String getObjectURL(String objectName) {
+ Date date = new Date();
+ DateTime dateTime = DateUtil.offsetMinute(date, 15);
+ URL url = amazonS3.generatePresignedUrl(ossProperties.getBucketName(), objectName, dateTime.toJdkDate());
+ return url.toString();
+ }
+
+ /**
+ * 获取文件
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @return 二进制流
+ * @see AWS
+ * API Documentation
+ */
+ @SneakyThrows
+ public S3Object getObject(String bucketName, String objectName) {
+ return amazonS3.getObject(bucketName, objectName);
+ }
+
+
+ /**
+ * 内网文件转OSS文件
+ *
+ * @param bucketName bucket名称
+ * @param fileName 文件名称
+ * @param url url
+ */
+// public void intranetToOSSUrl(String fileName,String url){
+// putObject(ossProperties.getBucketName(),fileName,HttpDownloader.downloadBytes(url));
+// }
+
+ /**
+ * 上传文件
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @param bytes 文件
+ * @throws Exception
+ */
+ public void putObject(String bucketName, String objectName, byte[] bytes) {
+ putObject(bucketName, objectName, bytes, bytes.length, "application/octet-stream");
+ }
+
+ /**
+ * 上传文件
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @param bytes 文件
+ * @param size 大小
+ * @param contextType 类型
+ * @throws Exception
+ * @see AWS
+ * API Documentation
+ */
+ public PutObjectResult putObject(String bucketName, String objectName, byte[] bytes, long size,
+ String contextType) {
+ ObjectMetadata objectMetadata = new ObjectMetadata();
+ objectMetadata.setContentLength(size);
+ objectMetadata.setContentType(contextType);
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
+ // 上传
+ return amazonS3.putObject(bucketName, objectName, byteArrayInputStream, objectMetadata);
+
+ }
+
+ /**
+ * 上传文件
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @param stream 文件流
+ * @throws Exception
+ */
+ public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
+ putObject(bucketName, objectName, stream, (long) stream.available(), "application/octet-stream");
+ }
+
+ /**
+ * 上传文件
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @param stream 文件流
+ * @param size 大小
+ * @param contextType 类型
+ * @throws Exception
+ * @see AWS
+ * API Documentation
+ */
+ public PutObjectResult putObject(String bucketName, String objectName, InputStream stream, long size,
+ String contextType) throws Exception {
+ com.amazonaws.services.s3.model.S3Object s3Object = new com.amazonaws.services.s3.model.S3Object();
+ // String fileName = getFileName(objectName);
+ byte[] bytes = IOUtils.toByteArray(stream);
+ ObjectMetadata objectMetadata = new ObjectMetadata();
+ objectMetadata.setContentLength(size);
+ objectMetadata.setContentType(contextType);
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
+ // 上传
+ return amazonS3.putObject(bucketName, objectName, byteArrayInputStream, objectMetadata);
+
+ }
+
+ /**
+ * 获取文件信息
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @see AWS
+ * API Documentation
+ */
+ public S3Object getObjectInfo(String bucketName, String objectName) throws Exception {
+ @Cleanup
+ S3Object object = amazonS3.getObject(bucketName, objectName);
+ return object;
+ }
+
+ /**
+ * 删除文件
+ * @param bucketName bucket名称
+ * @param objectName 文件名称
+ * @throws Exception
+ * @see AWS API
+ * Documentation
+ */
+ public void removeObject(String bucketName, String objectName) throws Exception {
+ amazonS3.deleteObject(bucketName, objectName);
+ }
+
+ @Override
+ public void afterPropertiesSet() {
+ System.setProperty("com.amazonaws.sdk.disableCertChecking", "true");
+ ClientConfiguration clientConfiguration = new ClientConfiguration();//初始化客户端config
+ clientConfiguration.setMaxConnections(ossProperties.getMaxConnections());
+ clientConfiguration.setProtocol(Protocol.HTTPS);//设置mos 请求协议为http
+ clientConfiguration.setSignerOverride("S3SignerType");
+ AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(
+ ossProperties.getEndpoint(), ossProperties.getRegion());//创建AWS凭证
+ AWSCredentials awsCredentials = new BasicAWSCredentials(ossProperties.getAccessKey(),
+ ossProperties.getSecretKey());
+ AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);
+ this.amazonS3 = AmazonS3Client.builder().withEndpointConfiguration(endpointConfiguration)
+ .withClientConfiguration(clientConfiguration).withCredentials(awsCredentialsProvider)
+ .disableChunkedEncoding().withPathStyleAccessEnabled(ossProperties.getPathStyleAccess()).build();
+ }
+
+}
diff --git a/yshop-oss/src/main/resources/META-INF/spring.factories b/yshop-oss/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..4bd900de
--- /dev/null
+++ b/yshop-oss/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ co.yixiang.oss.config.OssAutoConfiguration
diff --git a/yshop-tools/pom.xml b/yshop-tools/pom.xml
index d6c1dac0..0d6c6976 100644
--- a/yshop-tools/pom.xml
+++ b/yshop-tools/pom.xml
@@ -40,6 +40,13 @@
${qiniu.version}
+
+
+ co.yixiang
+ yshop-oss
+ 3.3
+
+
com.alipay.sdk
diff --git a/yshop-tools/src/main/java/co/yixiang/modules/tools/rest/UploadController.java b/yshop-tools/src/main/java/co/yixiang/modules/tools/rest/UploadController.java
index 5c504f08..3252100c 100644
--- a/yshop-tools/src/main/java/co/yixiang/modules/tools/rest/UploadController.java
+++ b/yshop-tools/src/main/java/co/yixiang/modules/tools/rest/UploadController.java
@@ -5,15 +5,17 @@
*/
package co.yixiang.modules.tools.rest;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.api.YshopException;
import co.yixiang.constant.ShopConstants;
import co.yixiang.constant.SystemConfigConstants;
import co.yixiang.enums.ShopCommonEnum;
import co.yixiang.modules.tools.service.dto.LocalStorageDto;
-import co.yixiang.modules.tools.domain.QiniuContent;
import co.yixiang.modules.tools.service.LocalStorageService;
-import co.yixiang.modules.tools.service.QiNiuService;
+import co.yixiang.oss.config.OssProperties;
+import co.yixiang.oss.service.OssTemplate;
import co.yixiang.utils.RedisUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -41,14 +43,16 @@ import java.util.Map;
public class UploadController {
private final LocalStorageService localStorageService;
- private final QiNiuService qiNiuService;
private final RedisUtils redisUtils;
+ private final OssProperties ossProperties;
+ private final OssTemplate ossTemplate;
- public UploadController(LocalStorageService localStorageService, QiNiuService qiNiuService,
- RedisUtils redisUtils) {
+ public UploadController(LocalStorageService localStorageService, RedisUtils redisUtils,
+ OssProperties ossProperties, OssTemplate ossTemplate) {
this.localStorageService = localStorageService;
- this.qiNiuService = qiNiuService;
this.redisUtils = redisUtils;
+ this.ossProperties = ossProperties;
+ this.ossTemplate = ossTemplate;
}
@@ -76,13 +80,21 @@ public class UploadController {
url = url.append(","+localUrl + "/file/" + localStorageDTO.getType() + "/" + localStorageDTO.getRealName());
}
}
- } else {//走七牛云
+ } else {
+ // 走oss存储
for (MultipartFile file : files) {
- QiniuContent qiniuContent = qiNiuService.upload(file, qiNiuService.find());
+ String [] originalFilename = file.getOriginalFilename().split("\\.");
+ String fileName = ossProperties.getBucketName()+"/file/"+originalFilename[0] + "-" + IdUtil.simpleUUID() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename());
+ try {
+ ossTemplate.putObject(ossProperties.getBucketName(), fileName, file.getInputStream());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ String fileUrl = String.format(ossProperties.getCustomDomain(), fileName);
if ("".equals(url.toString())) {
- url = url.append(qiniuContent.getUrl());
+ url = url.append(fileUrl);
}else{
- url = url.append(","+qiniuContent.getUrl());
+ url = url.append(","+fileUrl);
}
}
}