diff --git a/base-admin/src/main/java/com/agri/web/controller/common/CommonController.java b/base-admin/src/main/java/com/agri/web/controller/common/CommonController.java
index b26b209..70ad7b3 100644
--- a/base-admin/src/main/java/com/agri/web/controller/common/CommonController.java
+++ b/base-admin/src/main/java/com/agri/web/controller/common/CommonController.java
@@ -1,7 +1,13 @@
package com.agri.web.controller.common;
+import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+
+import com.agri.common.config.OSSConfig;
+import com.agri.common.utils.AliyunOSSUtils;
+import com.agri.common.utils.ApiUtils;
+import io.swagger.v3.oas.annotations.Operation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -31,6 +37,12 @@ public class CommonController
@Autowired
private ServerConfig serverConfig;
+ @Autowired
+ private AliyunOSSUtils aliyunOSSUtils;
+
+ @Autowired
+ private OSSConfig ossConfig;
+
/**
* 通用下载请求
*
@@ -67,22 +79,25 @@ public class CommonController
* 通用上传请求
*/
@PostMapping("/common/upload")
- public AjaxResult uploadFile(MultipartFile file) throws Exception
- {
- try
- {
+ public AjaxResult uploadFile(MultipartFile file) throws Exception {
+ try {
// 上传文件路径
String filePath = RuoYiConfig.getUploadPath();
- // 上传并返回新文件名称
- String fileName = FileUploadUtils.upload(filePath, file);
- String url = serverConfig.getUrl() + fileName;
+ String url = "";
+ String fileName = "";
+ if ("oss".equals(ossConfig.getUploadType())){
+ url = aliyunOSSUtils.upLoadFile(file);
+ fileName = FileUtils.getName(url);
+ }else {
+ // 上传并返回新文件名称
+ fileName = FileUploadUtils.upload(filePath, file);
+ url = serverConfig.getUrl() + fileName;
+ }
AjaxResult ajax = AjaxResult.success();
ajax.put("fileName", fileName);
ajax.put("url", url);
return ajax;
- }
- catch (Exception e)
- {
+ } catch (Exception e) {
return AjaxResult.error(e.getMessage());
}
}
@@ -115,4 +130,14 @@ public class CommonController
log.error("下载文件失败", e);
}
}
+
+ /**
+ * 获取上传文件签名
+ * @return
+ */
+ @Operation(summary = "获取上传文件签名",method = "GET")
+ @GetMapping("/getSign")
+ public String getOssSign() {
+ return ApiUtils.successData(aliyunOSSUtils.getSign());
+ }
}
diff --git a/base-admin/src/main/resources/application-dev.yml b/base-admin/src/main/resources/application-dev.yml
index 4ffb96e..8f6c7b5 100644
--- a/base-admin/src/main/resources/application-dev.yml
+++ b/base-admin/src/main/resources/application-dev.yml
@@ -226,3 +226,4 @@ sms:
signature: 青蛙农业
#模板ID 非必须配置,如果使用sendMessage的快速发送需此配置
template-id: SMS_473805253
+
diff --git a/base-admin/src/main/resources/application.yml b/base-admin/src/main/resources/application.yml
index 9733594..2e321c2 100644
--- a/base-admin/src/main/resources/application.yml
+++ b/base-admin/src/main/resources/application.yml
@@ -13,3 +13,15 @@ knife4j:
username: admin
# 密码
password: admin123
+
+# 阿里云相关配置
+aliyun:
+ oss:
+ endpoint: oss-cn-chengdu.aliyuncs.com
+ accessKeyId: LTAI5tEFj4BeiBfWgEDiRJn7
+ accessKeySecret: 4kOMnSCvTN9KAufb1ul0dHzQuYo8Mz
+ bucketName: gov-cloud
+ prefixKey: backend/
+ # domainName: https://ossnew.ljnhs.cn/
+ maxSize: 100 #文件大小限制(单位: m) 默认10m
+ uploadType: oss
diff --git a/base-common/pom.xml b/base-common/pom.xml
index 0fd4b6f..1879b83 100644
--- a/base-common/pom.xml
+++ b/base-common/pom.xml
@@ -137,6 +137,19 @@
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+ com.aliyun.oss
+ aliyun-sdk-oss
+ 3.10.2
+
\ No newline at end of file
diff --git a/base-common/src/main/java/com/agri/common/config/OSSConfig.java b/base-common/src/main/java/com/agri/common/config/OSSConfig.java
new file mode 100644
index 0000000..91eb910
--- /dev/null
+++ b/base-common/src/main/java/com/agri/common/config/OSSConfig.java
@@ -0,0 +1,60 @@
+package com.agri.common.config;
+
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+@Component("ossConfig")
+@ConfigurationProperties(prefix = "aliyun.oss")
+@Data
+public class OSSConfig {
+ /**
+ * OSS 访问域名
+ */
+ private String endpoint;
+ /**
+ * 标识用户
+ */
+ private String accessKeyId;
+ /**
+ * 加密签名字符串
+ */
+ private String accessKeySecret;
+ /**
+ * 存储空间名称
+ */
+ private String bucketName;
+
+ /**
+ * 文件/对象名称的前缀,类似目录
+ */
+ private String prefixKey;
+ /**
+ * 自定义域名,预览图片用到
+ */
+// private String domainName;
+ /**
+ * 文件大小限制(单位: m)
+ */
+ private Long maxSize;
+
+ /**
+ * 上传方式
+ */
+ private String uploadType;
+
+ @Bean
+ public OSS ossClient() {
+ return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+ }
+
+ public Long getMaxSize() {
+ if (maxSize == null || maxSize == 0) {
+ maxSize = 10L;
+ }
+ return maxSize * 1024 * 1204;
+ }
+}
diff --git a/base-common/src/main/java/com/agri/common/exception/BusinessException.java b/base-common/src/main/java/com/agri/common/exception/BusinessException.java
new file mode 100644
index 0000000..269ccc3
--- /dev/null
+++ b/base-common/src/main/java/com/agri/common/exception/BusinessException.java
@@ -0,0 +1,47 @@
+package com.agri.common.exception;
+
+public class BusinessException extends RuntimeException {
+
+ private String code;
+ private final String message;
+
+ private Object data;
+
+ public BusinessException(String code, String message) {
+ this.message = message;
+ this.code = code;
+ }
+
+ public BusinessException(String code, String message, Object data) {
+ this.message = message;
+ this.code = code;
+ this.data = data;
+ }
+
+
+ public BusinessException(String message) {
+ this.message = message;
+ this.code = "0";
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ /**
+ * 去除异常中的堆栈跟踪信息,减小异常控制代码流性能损耗
+ */
+ // @Override
+ // public Throwable fillInStackTrace() {
+ // return this;
+ // }
+}
diff --git a/base-common/src/main/java/com/agri/common/utils/AliyunOSSUtils.java b/base-common/src/main/java/com/agri/common/utils/AliyunOSSUtils.java
new file mode 100644
index 0000000..aeec577
--- /dev/null
+++ b/base-common/src/main/java/com/agri/common/utils/AliyunOSSUtils.java
@@ -0,0 +1,205 @@
+package com.agri.common.utils;
+
+
+import com.agri.common.config.OSSConfig;
+import com.agri.common.exception.BusinessException;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.common.utils.BinaryUtil;
+import com.aliyun.oss.model.MatchMode;
+import com.aliyun.oss.model.PolicyConditions;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.UUID;
+
+@Slf4j
+@Component
+public class AliyunOSSUtils {
+
+ /**
+ * 图片格式
+ */
+ private static final String[] FILE_TYPE = new String[]{".bmp", ".jpg",
+ ".jpeg", ".gif", ".png", ".mp4", ".jfif", ".ico", ".pdf"};
+
+ @Resource
+ private OSS ossClient;
+
+ @Resource
+ private OSSConfig ossConfig;
+
+ /**
+ * 图像上传
+ *
+ * @param uploadFile 图像流处理
+ * @return 文件访问路径
+ */
+ public String upLoadFile(MultipartFile uploadFile) {
+ return ossPutObject(uploadFile, null);
+ }
+
+ /**
+ * 图像上传
+ *
+ * @param uploadFile 图像流处理
+ * @param prefixKey 文件/对象名称的前缀,类似目录,例如:backend/
+ * @return 文件访问路径
+ */
+ public String upLoadFile(MultipartFile uploadFile, String prefixKey) {
+ return ossPutObject(uploadFile, prefixKey);
+ }
+
+ @Deprecated
+ public String uploadAvatar(MultipartFile uploadFile) {
+ return ossPutObject(uploadFile,null);
+ }
+
+ /**
+ * 图片上传
+ *
+ * @param inputStream 图像流处理
+ * @return 文件访问路径
+ */
+ @Deprecated
+ public String upLoadFile(InputStream inputStream) {
+ String suffix = ".png";
+ //文件名
+ String key = ossConfig.getPrefixKey() + UUID.randomUUID().toString()
+ .replace("-", "") + suffix;
+ try {
+ ossClient.putObject(ossConfig.getBucketName(), key, inputStream);
+ inputStream.close();
+ log.info("--------图片上传成功--------");
+ } catch (Exception e) {
+ log.info("oos上传失败:" + e.getMessage());
+ throw new BusinessException("图片上传失败");
+ }
+ //返回文件访问路径
+ return key;
+ }
+
+ /**
+ * 图片上传
+ *
+ * @param inputStream 图像流处理
+ * @return 文件访问路径
+ */
+ public String upLoadOtherFile(InputStream inputStream, String filename) {
+ String suffix = filename.substring(filename.lastIndexOf("."));
+ //文件名
+ String key = ossConfig.getPrefixKey() + UUID.randomUUID().toString()
+ .replace("-", "") + suffix;
+ try {
+ ossClient.putObject(ossConfig.getBucketName(), key, inputStream);
+ inputStream.close();
+ } catch (Exception e) {
+ log.error("oos上传失败:{}", e.getMessage());
+ throw new BusinessException("文件上传失败");
+ }
+ //返回文件访问路径
+ return key;
+ }
+
+ /**
+ * 校验文件后缀
+ *
+ * @param suffix 文件后缀
+ * @return
+ */
+ private void verifySuffix(String suffix) {
+ // 校验文件格式
+ for (String type : FILE_TYPE) {
+ if (type.equalsIgnoreCase(suffix)) {
+ return;
+ }
+ }
+ throw new BusinessException("暂不支持此格式的文件");
+ }
+
+ /**
+ * 获取签名
+ *
+ * @return
+ */
+ public Map getSign() {
+ String accessId = ossConfig.getAccessKeyId(); // 请填写您的AccessKeyId。
+ String endpoint = ossConfig.getEndpoint(); // 请填写您的 endpoint。
+ String bucket = ossConfig.getBucketName(); // 请填写您的 bucketname 。
+ String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
+ String dir = ossConfig.getPrefixKey(); // 用户上传文件时指定的前缀。
+
+ try {
+ long expireTime = 180;//60秒
+ long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
+ Date expiration = new Date(expireEndTime);
+ PolicyConditions policyConds = new PolicyConditions();
+ policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
+ policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
+
+ String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
+ byte[] binaryData = postPolicy.getBytes("utf-8");
+ String encodedPolicy = BinaryUtil.toBase64String(binaryData);
+ String postSignature = ossClient.calculatePostSignature(postPolicy);
+
+ Map respMap = new LinkedHashMap<>();
+ respMap.put("accessid", accessId);
+ respMap.put("policy", encodedPolicy);
+ respMap.put("signature", postSignature);
+ respMap.put("dir", dir);
+ respMap.put("host", host);
+ respMap.put("expire", String.valueOf(expireEndTime / 1000));
+
+ return respMap;
+
+ } catch (Exception e) {
+ // Assert.fail(e.getMessage());
+ System.out.println(e.getMessage());
+ throw new BusinessException("获取签名失败");
+ }
+ }
+
+ /**
+ * oss 文件上传并获得访问路径
+ *
+ * @param uploadFile 需要上传的文件
+ * @param prefixKey 文件/对象名称的前缀,类似目录 例如:backend/
+ * @return
+ */
+ private String ossPutObject(MultipartFile uploadFile, String prefixKey) {
+
+ //获取文件名称
+ String originalFilename = uploadFile.getOriginalFilename();
+ //文件后缀
+ String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
+ verifySuffix(suffix);
+ long size = uploadFile.getSize();
+ if (size > ossConfig.getMaxSize()) {
+ throw new BusinessException("文件超出大小限制");
+ }
+ //前缀,类似目录
+ if (StringUtils.isBlank(prefixKey)) {
+ prefixKey = ossConfig.getPrefixKey();
+ }
+ //文件路径=prefixKey+文件名称
+ String key = prefixKey + UUID.randomUUID().toString()
+ .replace("-", "") + suffix;
+ try {
+ InputStream inputStream = uploadFile.getInputStream();
+ ossClient.putObject(ossConfig.getBucketName(), key, inputStream);
+ inputStream.close();
+ log.info("--------文件上传成功--------");
+ } catch (Exception e) {
+ log.error("oos上传失败:", e);
+ throw new BusinessException("图片上传失败");
+ }
+ //返回文件访问路径
+ return key;
+ }
+
+}
diff --git a/base-common/src/main/java/com/agri/common/utils/ApiUtils.java b/base-common/src/main/java/com/agri/common/utils/ApiUtils.java
new file mode 100644
index 0000000..6225682
--- /dev/null
+++ b/base-common/src/main/java/com/agri/common/utils/ApiUtils.java
@@ -0,0 +1,123 @@
+package com.agri.common.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.serializer.SerializeConfig;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+
+@Data
+public class ApiUtils {
+ /** 成功code */
+ public static final int SUCCESS_CODE = 200;
+ /** 成功消息 */
+ public static final String SUCCESS_MESSAGE = "操作成功";
+ /** 错误code */
+ public static final int ERROR_CODE = 500;
+ /** 错误消息 */
+ public static final String ERROR_MESSAGE = "操作失败";
+ /** api登录失效 */
+ public static final String LOGIN_FAILURE = "10001";
+ /** 驴团长api登录失效 */
+ public static final String GROUPBUY_LOGIN_FAILURE = "110001";
+ /** 缺少服务商(企业)id参数 **/
+ public static final String ENTERPRISEID_MISS = "10002";
+
+ /** 订单提示弹窗 **/
+ public static final String ORDER_TIPS = "10003";
+ /** 商品详情error显示占位图 */
+ public static final String GOODS_DETAILS_ERROR = "10005";
+
+ /** 服务商品库存不足 */
+ public static final String UNDER_STOCK = "10006";
+
+ /** 商品已存在 */
+ public static final String GOODS_EXISTS = "10007";
+
+ /** 数据不存在 */
+ public static final String DATA_NOT_EXISTS = "10008";
+
+ /** 硬弹框code */
+ public static final String HARDFRAME = "33333";
+
+ /** 未注册弹窗 */
+ public static final String UNRFGISTERED_TIPS = "12100";
+
+ /** 用户被禁用 */
+ public static final String USER_DISABLED = "12101";
+
+ /** 城市合伙人权限未开通 */
+ public static final String USER_AUTH_FAILURE = "12102";
+
+ /** 再来一单所有商品失效 */
+ public static final String all_goods_effective = "44444";
+
+ private Integer code;
+ private String msg;
+ private Object data = new HashMap<>();
+
+ public ApiUtils() {}
+
+ public ApiUtils(Object data) {
+ this.code = SUCCESS_CODE;
+ if(data!=null){
+ this.data = data;
+ }
+ this.msg = SUCCESS_MESSAGE;
+ }
+ public ApiUtils(Integer code, String message) {
+ this.code = code;
+ this.msg = message;
+ }
+ public ApiUtils(Integer code, String message, Object data) {
+ this.code = code;
+ this.msg = message;
+ this.data = data;
+ }
+
+ public static SerializeConfig config = new SerializeConfig();
+ //对象为null返回{}
+ //枚举类型处理
+ public static SerializerFeature[] reatures = new SerializerFeature[] {
+ SerializerFeature.WriteMapNullValue,//为null也返回
+ SerializerFeature.WriteNullStringAsEmpty,//字符串为null,返回""
+ SerializerFeature.WriteNullListAsEmpty,//数组/列表为null,返回[]
+ SerializerFeature.WriteNullNumberAsZero,//数值类型(Integer,Long)为null,返回0
+ SerializerFeature.DisableCircularReferenceDetect,// 消除循环引用
+ };
+
+ static {
+ config.put(Date.class, new SimpleDateFormatSerializer());//日期类型处理,为null返回""
+ config.put(BigDecimal.class, new BigDecimalSerializer());//BigDecimal类型处理,为null返回"0"
+ config.setAsmEnable(false);
+ }
+
+ public static String error() {
+ return JSON.toJSONString(new ApiUtils(ERROR_CODE, ERROR_MESSAGE.toString()), config, reatures);
+ }
+ public static String error(String message) {
+ return JSON.toJSONString(new ApiUtils(ERROR_CODE,message), config, reatures);
+ }
+ public static String error(Integer code, String message) {
+ return JSON.toJSONString(new ApiUtils(code,message), config, reatures);
+ }
+ public static String success() {
+ return JSON.toJSONString(new ApiUtils(SUCCESS_CODE, SUCCESS_MESSAGE.toString()), config, reatures);
+ }
+ public static String success(Integer code, String message){
+ return JSON.toJSONString(new ApiUtils(code, message), config, reatures);
+ }
+ public static String success(String message) {
+ return JSON.toJSONString(new ApiUtils(SUCCESS_CODE, message), config, reatures);
+ }
+ public static String successData(Object data) {
+ return JSON.toJSONString(new ApiUtils(data), config, reatures);
+ }
+ public static String resultData(Integer code, String message, Object data) {
+ return JSON.toJSONString(new ApiUtils(code, message, data), config, reatures);
+ }
+}
+
diff --git a/base-common/src/main/java/com/agri/common/utils/BigDecimalSerializer.java b/base-common/src/main/java/com/agri/common/utils/BigDecimalSerializer.java
new file mode 100644
index 0000000..ec25b06
--- /dev/null
+++ b/base-common/src/main/java/com/agri/common/utils/BigDecimalSerializer.java
@@ -0,0 +1,19 @@
+package com.agri.common.utils;
+
+import com.alibaba.fastjson.serializer.JSONSerializer;
+import com.alibaba.fastjson.serializer.ObjectSerializer;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+
+public class BigDecimalSerializer implements ObjectSerializer {
+
+ @Override
+ public void write(JSONSerializer serializer, Object object, Object o1, Type type, int i) throws IOException {
+ if(object == null) {
+ serializer.write("0.00");
+ return ;
+ }
+ serializer.write(String.format("%.2f", object));
+ }
+}
diff --git a/base-common/src/main/java/com/agri/common/utils/SimpleDateFormatSerializer.java b/base-common/src/main/java/com/agri/common/utils/SimpleDateFormatSerializer.java
new file mode 100644
index 0000000..150c903
--- /dev/null
+++ b/base-common/src/main/java/com/agri/common/utils/SimpleDateFormatSerializer.java
@@ -0,0 +1,29 @@
+package com.agri.common.utils;
+
+import com.alibaba.fastjson.serializer.JSONSerializer;
+import com.alibaba.fastjson.serializer.ObjectSerializer;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class SimpleDateFormatSerializer implements ObjectSerializer {
+
+ private final String timePattern="yyyy-MM-dd HH:mm:ss";
+ private final String datePattern="yyyy-MM-dd";
+
+ @Override
+ public void write(JSONSerializer serializer, Object object, Object o1, Type type, int i) throws IOException {
+ if (object == null) {
+ serializer.getWriter().write("\"\"");
+ return;
+ }
+
+ Date date = (Date) object;
+ SimpleDateFormat format = new SimpleDateFormat(timePattern);
+
+ String text = format.format(date);
+ serializer.write(text);
+ }
+}
diff --git a/base-common/src/main/java/com/agri/common/utils/file/FileUtils.java b/base-common/src/main/java/com/agri/common/utils/file/FileUtils.java
index ad83d10..a51d31d 100644
--- a/base-common/src/main/java/com/agri/common/utils/file/FileUtils.java
+++ b/base-common/src/main/java/com/agri/common/utils/file/FileUtils.java
@@ -25,6 +25,12 @@ import com.agri.common.utils.uuid.IdUtils;
*/
public class FileUtils
{
+ /** 字符常量:斜杠 {@code '/'} */
+ public static final char SLASH = '/';
+
+ /** 字符常量:反斜杠 {@code '\\'} */
+ public static final char BACKSLASH = '\\';
+
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
/**
@@ -256,4 +262,55 @@ public class FileUtils
}
return strFileExtendName;
}
+
+ /**
+ * 返回文件名
+ *
+ * @param filePath 文件
+ * @return 文件名
+ */
+ public static String getName(String filePath)
+ {
+ if (null == filePath)
+ {
+ return null;
+ }
+ int len = filePath.length();
+ if (0 == len)
+ {
+ return filePath;
+ }
+ if (isFileSeparator(filePath.charAt(len - 1)))
+ {
+ // 以分隔符结尾的去掉结尾分隔符
+ len--;
+ }
+
+ int begin = 0;
+ char c;
+ for (int i = len - 1; i > -1; i--)
+ {
+ c = filePath.charAt(i);
+ if (isFileSeparator(c))
+ {
+ // 查找最后一个路径分隔符(/或者\)
+ begin = i + 1;
+ break;
+ }
+ }
+
+ return filePath.substring(begin, len);
+ }
+
+ /**
+ * 是否为Windows或者Linux(Unix)文件分隔符
+ * Windows平台下分隔符为\,Linux(Unix)为/
+ *
+ * @param c 字符
+ * @return 是否为Windows或者Linux(Unix)文件分隔符
+ */
+ public static boolean isFileSeparator(char c)
+ {
+ return SLASH == c || BACKSLASH == c;
+ }
}