diff --git a/buyer-api/src/test/java/cn/lili/buyer/test/cart/FileTest.java b/buyer-api/src/test/java/cn/lili/buyer/test/cart/FileTest.java
index 1ccf3cff..b7907bca 100644
--- a/buyer-api/src/test/java/cn/lili/buyer/test/cart/FileTest.java
+++ b/buyer-api/src/test/java/cn/lili/buyer/test/cart/FileTest.java
@@ -1,7 +1,7 @@
package cn.lili.buyer.test.cart;
-import cn.lili.modules.file.plugin.FileManagerPlugin;
+import cn.lili.modules.file.plugin.FilePlugin;
import cn.lili.modules.goods.entity.dos.Brand;
import cn.lili.modules.goods.service.BrandService;
import com.xkcoding.http.util.StringUtil;
@@ -27,7 +27,7 @@ class FileTest {
@Autowired
- private FileManagerPlugin fileManagerPlugin;
+ private FilePlugin fileManagerPlugin;
@Autowired
private BrandService brandService;
diff --git a/common-api/src/main/java/cn/lili/controller/common/UploadController.java b/common-api/src/main/java/cn/lili/controller/common/UploadController.java
index 25001d07..d97fa40c 100644
--- a/common-api/src/main/java/cn/lili/controller/common/UploadController.java
+++ b/common-api/src/main/java/cn/lili/controller/common/UploadController.java
@@ -12,7 +12,8 @@ import cn.lili.common.utils.Base64DecodeMultipartFile;
import cn.lili.common.utils.CommonUtil;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.file.entity.File;
-import cn.lili.modules.file.plugin.FileManagerPlugin;
+import cn.lili.modules.file.plugin.FilePlugin;
+import cn.lili.modules.file.plugin.FilePluginFactory;
import cn.lili.modules.file.service.FileService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.enums.SettingEnum;
@@ -47,7 +48,7 @@ public class UploadController {
@Autowired
private SettingService settingService;
@Autowired
- private FileManagerPlugin fileManagerPlugin;
+ private FilePluginFactory filePluginFactory;
@Autowired
private Cache cache;
@@ -86,7 +87,7 @@ public class UploadController {
try {
InputStream inputStream = file.getInputStream();
//上传至第三方云服务或服务器
- result = fileManagerPlugin.inputStreamUpload(inputStream, fileKey);
+ result = filePluginFactory.filePlugin().inputStreamUpload(inputStream, fileKey);
//保存数据信息至数据库
newFile.setName(file.getOriginalFilename());
newFile.setFileSize(file.getSize());
diff --git a/framework/pom.xml b/framework/pom.xml
index 6919e763..5974c103 100644
--- a/framework/pom.xml
+++ b/framework/pom.xml
@@ -420,6 +420,13 @@
+
+ io.minio
+ minio
+ ${minio.version}
+
+
+
diff --git a/framework/src/main/java/cn/lili/modules/file/entity/enums/OssEnum.java b/framework/src/main/java/cn/lili/modules/file/entity/enums/OssEnum.java
new file mode 100644
index 00000000..748faeca
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/file/entity/enums/OssEnum.java
@@ -0,0 +1,17 @@
+package cn.lili.modules.file.entity.enums;
+
+import com.aliyun.oss.OSS;
+
+/**
+ * OssEnum
+ *
+ * @author Chopper
+ * @version v1.0
+ * 2022-06-06 11:23
+ */
+public enum OssEnum {
+ /**
+ *
+ */
+ ALI_OSS, MINIO;
+}
diff --git a/framework/src/main/java/cn/lili/modules/file/plugin/FileManagerPlugin.java b/framework/src/main/java/cn/lili/modules/file/plugin/FilePlugin.java
similarity index 77%
rename from framework/src/main/java/cn/lili/modules/file/plugin/FileManagerPlugin.java
rename to framework/src/main/java/cn/lili/modules/file/plugin/FilePlugin.java
index bd279d05..2f6fa799 100644
--- a/framework/src/main/java/cn/lili/modules/file/plugin/FileManagerPlugin.java
+++ b/framework/src/main/java/cn/lili/modules/file/plugin/FilePlugin.java
@@ -1,16 +1,23 @@
package cn.lili.modules.file.plugin;
+import cn.lili.modules.file.entity.enums.OssEnum;
+
import java.io.InputStream;
import java.util.List;
/**
- * 文件管理插件
+ * 文件插件接口
*
* @author Chopper
*/
-public interface FileManagerPlugin {
+public interface FilePlugin {
+ /**
+ * 插件名称
+ */
+ OssEnum pluginName();
+
/**
* 文件路径上传
*
diff --git a/framework/src/main/java/cn/lili/modules/file/plugin/FilePluginFactory.java b/framework/src/main/java/cn/lili/modules/file/plugin/FilePluginFactory.java
new file mode 100644
index 00000000..63e4da08
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/file/plugin/FilePluginFactory.java
@@ -0,0 +1,59 @@
+package cn.lili.modules.file.plugin;
+
+import cn.hutool.json.JSONUtil;
+import cn.lili.common.exception.ServiceException;
+import cn.lili.modules.file.entity.enums.OssEnum;
+import cn.lili.modules.file.plugin.impl.AliFilePlugin;
+import cn.lili.modules.file.plugin.impl.MinioFilePlugin;
+import cn.lili.modules.system.entity.dos.Setting;
+import cn.lili.modules.system.entity.dto.OssSetting;
+import cn.lili.modules.system.entity.enums.SettingEnum;
+import cn.lili.modules.system.service.SettingService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 文件服务抽象工厂 直接返回操作类
+ *
+ * @author Chopper
+ * @version v1.0
+ * 2022-06-06 11:35
+ */
+@Component
+public class FilePluginFactory {
+
+
+ @Autowired
+ private SettingService settingService;
+
+
+ /**
+ * 获取oss client
+ *
+ * @return
+ */
+ public FilePlugin filePlugin() {
+
+ OssSetting ossSetting = null;
+ try {
+ Setting setting = settingService.get(SettingEnum.OSS_SETTING.name());
+
+ ossSetting = JSONUtil.toBean(setting.getSettingValue(), OssSetting.class);
+
+
+ switch (OssEnum.valueOf(ossSetting.getType())) {
+
+ case MINIO:
+ return new MinioFilePlugin(ossSetting);
+ case ALI_OSS:
+ return new AliFilePlugin(ossSetting);
+ default:
+ throw new ServiceException();
+ }
+ } catch (Exception e) {
+ throw new ServiceException();
+ }
+ }
+
+
+}
diff --git a/framework/src/main/java/cn/lili/modules/file/plugin/impl/AliFileManagerPlugin.java b/framework/src/main/java/cn/lili/modules/file/plugin/impl/AliFilePlugin.java
similarity index 72%
rename from framework/src/main/java/cn/lili/modules/file/plugin/impl/AliFileManagerPlugin.java
rename to framework/src/main/java/cn/lili/modules/file/plugin/impl/AliFilePlugin.java
index 4ddbf899..e195a2a0 100644
--- a/framework/src/main/java/cn/lili/modules/file/plugin/impl/AliFileManagerPlugin.java
+++ b/framework/src/main/java/cn/lili/modules/file/plugin/impl/AliFilePlugin.java
@@ -1,23 +1,17 @@
package cn.lili.modules.file.plugin.impl;
-import cn.hutool.core.util.StrUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
-import cn.lili.modules.file.plugin.FileManagerPlugin;
-import cn.lili.modules.system.entity.dos.Setting;
+import cn.lili.modules.file.entity.enums.OssEnum;
+import cn.lili.modules.file.plugin.FilePlugin;
import cn.lili.modules.system.entity.dto.OssSetting;
-import cn.lili.modules.system.entity.enums.SettingEnum;
-import cn.lili.modules.system.service.SettingService;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.ObjectMetadata;
-import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
import java.io.File;
import java.io.InputStream;
@@ -29,28 +23,19 @@ import java.util.List;
* @author Chopper
*/
-@Component
@Slf4j
-public class AliFileManagerPlugin implements FileManagerPlugin {
+public class AliFilePlugin implements FilePlugin {
- @Autowired
- private SettingService settingService;
+ private OssSetting ossSetting;
- /**
- * 下一个初始化配置参数的时间
- * 这里为了防止多次调用redis,减少与redis的交互时间
- */
- private static Long nextInitSetting;
+ public AliFilePlugin(OssSetting ossSetting) {
+ this.ossSetting = ossSetting;
+ }
- /**
- * 暂时设定3分账请求一次设置
- */
- private static final Long INTERVAL = 60 * 3 * 1000L;
-
- /**
- * 静态设置,最快三分钟更新一次
- */
- private static OssSetting ossSetting;
+ @Override
+ public OssEnum pluginName() {
+ return OssEnum.ALI_OSS;
+ }
/**
* 获取oss client
@@ -58,32 +43,12 @@ public class AliFileManagerPlugin implements FileManagerPlugin {
* @return
*/
private OSS getOssClient() {
- OssSetting ossSetting = getSetting();
-
return new OSSClientBuilder().build(
ossSetting.getEndPoint(),
ossSetting.getAccessKeyId(),
ossSetting.getAccessKeySecret());
}
- /**
- * 获取配置
- *
- * @return
- */
- private OssSetting getSetting() {
- //如果没有配置,或者没有下次刷新时间,或者下次刷新时间小于当前时间,则从redis 更新一次
- if (ossSetting == null || nextInitSetting == null || nextInitSetting < System.currentTimeMillis()) {
- Setting setting = settingService.get(SettingEnum.OSS_SETTING.name());
- if (setting == null || StrUtil.isBlank(setting.getSettingValue())) {
- throw new ServiceException(ResultCode.OSS_NOT_EXIST);
- }
- nextInitSetting = System.currentTimeMillis() + INTERVAL;
- ossSetting = new Gson().fromJson(setting.getSettingValue(), OssSetting.class);
- return ossSetting;
- }
- return ossSetting;
- }
/**
* 获取配置前缀
@@ -91,7 +56,6 @@ public class AliFileManagerPlugin implements FileManagerPlugin {
* @return
*/
private String getUrlPrefix() {
- OssSetting ossSetting = getSetting();
return "https://" + ossSetting.getBucketName() + "." + ossSetting.getEndPoint() + "/";
}
@@ -130,7 +94,7 @@ public class AliFileManagerPlugin implements FileManagerPlugin {
try {
ObjectMetadata meta = new ObjectMetadata();
meta.setContentType("image/jpg");
- ossClient.putObject(getSetting().getBucketName(), key, inputStream, meta);
+ ossClient.putObject(ossSetting.getBucketName(), key, inputStream, meta);
} catch (OSSException oe) {
log.error("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
@@ -161,7 +125,7 @@ public class AliFileManagerPlugin implements FileManagerPlugin {
try {
ossClient.deleteObjects(
- new DeleteObjectsRequest(getSetting().getBucketName()).withKeys(key));
+ new DeleteObjectsRequest(ossSetting.getBucketName()).withKeys(key));
} catch (OSSException oe) {
log.error("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
diff --git a/framework/src/main/java/cn/lili/modules/file/plugin/impl/MinioFilePlugin.java b/framework/src/main/java/cn/lili/modules/file/plugin/impl/MinioFilePlugin.java
new file mode 100644
index 00000000..67471641
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/file/plugin/impl/MinioFilePlugin.java
@@ -0,0 +1,165 @@
+package cn.lili.modules.file.plugin.impl;
+
+import cn.lili.modules.file.entity.enums.OssEnum;
+import cn.lili.modules.file.plugin.FilePlugin;
+import cn.lili.modules.system.entity.dto.OssSetting;
+import io.minio.*;
+import io.minio.errors.ErrorResponseException;
+import io.minio.messages.DeleteObject;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+/**
+ * MINIO文件插件
+ *
+ * @author liushuai(liushuai711 @ gmail.com)
+ * @version v4.0
+ * @Description:
+ * @since 2022/6/6 17:45
+ */
+@Slf4j
+public class MinioFilePlugin implements FilePlugin {
+
+ private OssSetting ossSetting;
+
+ public MinioFilePlugin(OssSetting ossSetting) {
+ this.ossSetting = ossSetting;
+ }
+
+ /**
+ * 桶占位符
+ */
+ private static final String BUCKET_PARAM = "${bucket}";
+ /**
+ * bucket权限-只读
+ */
+ private static final String READ_ONLY = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
+ /**
+ * bucket权限-只读
+ */
+ private static final String WRITE_ONLY = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
+ /**
+ * bucket权限-读写
+ */
+ private static final String READ_WRITE = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
+
+
+ private MinioClient minioClient;
+
+
+ @Override
+ public OssEnum pluginName() {
+ return OssEnum.MINIO;
+ }
+
+ @Override
+ public String pathUpload(String filePath, String key) {
+ try {
+ return this.inputStreamUpload(new FileInputStream(filePath), key);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ public String inputStreamUpload(InputStream inputStream, String key) {
+ String bucket = "";
+ try {
+ MinioClient client = getOssClient();
+ bucket = ossSetting.getM_bucketName();
+ PutObjectArgs putObjectArgs = PutObjectArgs.builder()
+ .bucket(bucket).stream(inputStream, inputStream.available(), 5 * 1024 * 1024)
+ .object(key)
+ .contentType("image/png")
+ .build();
+ client.putObject(putObjectArgs);
+ } catch (ErrorResponseException e) {
+ e.printStackTrace();
+ return null;
+ } catch (Exception e) {
+ log.error("上传失败2,", e);
+ return null;
+ }
+ //拼接出可访问的url地址
+ return ossSetting.getM_endpoint() + "/" + bucket + "/" + key;
+ }
+
+
+ @Override
+ public void deleteFile(List key) {
+ if (key == null || key.isEmpty()) {
+ return;
+ }
+ MinioClient ossClient = getOssClient();
+ List objectList = key.stream().map(DeleteObject::new).collect(Collectors.toList());
+ ossClient.removeObjects(RemoveObjectsArgs.builder().objects(objectList).build());
+ }
+
+
+ /**
+ * 获取oss client
+ *
+ * @return
+ */
+ private MinioClient getOssClient() {
+ if (minioClient != null) {
+ return this.minioClient;
+ }
+ synchronized (this) {
+ if (minioClient == null) {
+ //创建客户端
+ this.minioClient = MinioClient.builder()
+ .endpoint(ossSetting.getM_endpoint())
+ .credentials(ossSetting.getM_accessKey(), ossSetting.getM_secretKey())
+ .build();
+ try {
+ //查看对应的bucket是否已经存在,不存在则创建
+ if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(ossSetting.getM_bucketName()).build())) {
+ //创建bucket
+ MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(ossSetting.getM_bucketName()).build();
+ this.minioClient.makeBucket(makeBucketArgs);
+ setBucketPolicy(this.minioClient, ossSetting.getM_bucketName(), "read-write");
+ log.info("创建minio桶成功{}", ossSetting.getM_bucketName());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ log.error("创建[{}]bucket失败", ossSetting.getM_bucketName());
+ }
+ }
+ }
+ return minioClient;
+ }
+
+
+ /**
+ * 更新桶权限策略
+ *
+ * @param bucket 桶
+ * @param policy 权限
+ */
+ public static void setBucketPolicy(MinioClient client, String bucket, String policy) throws Exception {
+ switch (policy) {
+ case "read-only":
+ client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(READ_ONLY.replace(BUCKET_PARAM, bucket)).build());
+ break;
+ case "write-only":
+ client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(WRITE_ONLY.replace(BUCKET_PARAM, bucket)).build());
+ break;
+ case "read-write":
+ client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).region("public").config(READ_WRITE.replace(BUCKET_PARAM, bucket)).build());
+ break;
+ case "none":
+ default:
+ break;
+ }
+ }
+
+
+}
diff --git a/framework/src/main/java/cn/lili/modules/file/serviceimpl/FileServiceImpl.java b/framework/src/main/java/cn/lili/modules/file/serviceimpl/FileServiceImpl.java
index 4d68c0f5..bc830cce 100644
--- a/framework/src/main/java/cn/lili/modules/file/serviceimpl/FileServiceImpl.java
+++ b/framework/src/main/java/cn/lili/modules/file/serviceimpl/FileServiceImpl.java
@@ -9,7 +9,8 @@ import cn.lili.common.vo.SearchVO;
import cn.lili.modules.file.entity.File;
import cn.lili.modules.file.entity.dto.FileOwnerDTO;
import cn.lili.modules.file.mapper.FileMapper;
-import cn.lili.modules.file.plugin.FileManagerPlugin;
+import cn.lili.modules.file.plugin.FilePlugin;
+import cn.lili.modules.file.plugin.FilePluginFactory;
import cn.lili.modules.file.service.FileService;
import cn.lili.mybatis.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -31,7 +32,7 @@ import java.util.List;
public class FileServiceImpl extends ServiceImpl implements FileService {
@Autowired
- private FileManagerPlugin fileManagerPlugin;
+ private FilePluginFactory filePluginFactory;
@Override
public void batchDelete(List ids) {
@@ -42,7 +43,7 @@ public class FileServiceImpl extends ServiceImpl implements Fi
List files = this.list(queryWrapper);
List keys = new ArrayList<>();
files.forEach(item -> keys.add(item.getFileKey()));
- fileManagerPlugin.deleteFile(keys);
+ filePluginFactory.filePlugin().deleteFile(keys);
this.remove(queryWrapper);
}
@@ -68,7 +69,7 @@ public class FileServiceImpl extends ServiceImpl implements Fi
List files = this.list(queryWrapper);
List keys = new ArrayList<>();
files.forEach(item -> keys.add(item.getFileKey()));
- fileManagerPlugin.deleteFile(keys);
+ filePluginFactory.filePlugin().deleteFile(keys);
this.remove(queryWrapper);
}
diff --git a/framework/src/main/java/cn/lili/modules/system/entity/dto/OssSetting.java b/framework/src/main/java/cn/lili/modules/system/entity/dto/OssSetting.java
index 80c5fd07..fd71d3b3 100644
--- a/framework/src/main/java/cn/lili/modules/system/entity/dto/OssSetting.java
+++ b/framework/src/main/java/cn/lili/modules/system/entity/dto/OssSetting.java
@@ -1,5 +1,7 @@
package cn.lili.modules.system.entity.dto;
+import cn.lili.common.utils.StringUtils;
+import cn.lili.modules.file.entity.enums.OssEnum;
import lombok.Data;
import java.io.Serializable;
@@ -15,6 +17,12 @@ import java.io.Serializable;
public class OssSetting implements Serializable {
private static final long serialVersionUID = 2975271656230801861L;
+
+ /**
+ * oss类型
+ */
+ private String type;
+
/**
* 域名
*/
@@ -35,4 +43,34 @@ public class OssSetting implements Serializable {
* 密钥
*/
private String accessKeySecret = "";
+
+
+ /**
+ * minio服务地址
+ */
+ private String m_endpoint;
+
+ /**
+ * minio用户名
+ */
+ private String m_accessKey;
+
+ /**
+ * minio密码
+ */
+ private String m_secretKey;
+
+ /**
+ * minio bucket名称
+ */
+ private String m_bucketName;
+
+
+ public String getType() {
+ //默认给阿里云oss存储类型
+ if (StringUtils.isEmpty(type)) {
+ return OssEnum.ALI_OSS.name();
+ }
+ return type;
+ }
}
diff --git a/pom.xml b/pom.xml
index a9d92a59..99b15f0a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -60,6 +60,7 @@
1.2.2
2.3.1
20211018.2
+ 8.0.3