targetCls) {
+ T target = null;
+ if (Utility.objIsNotNull(source)) {
+ try {
+ target = BeanUtils.instantiateClass(targetCls);
+ BeanUtils.copyProperties(source, target);
+ } catch (BeansException e) {
+ log.warn("copyBean error, e = {}", e);
+ }
+ }
+ return target;
+ }
+}
diff --git a/oss-common/src/main/java/cn/axzo/oss/common/utils/JsonUtil.java b/oss-common/src/main/java/cn/axzo/oss/common/utils/JsonUtil.java
new file mode 100644
index 0000000..f834e39
--- /dev/null
+++ b/oss-common/src/main/java/cn/axzo/oss/common/utils/JsonUtil.java
@@ -0,0 +1,21 @@
+package cn.axzo.oss.common.utils;
+
+import com.alibaba.fastjson.JSONObject;
+
+/**
+ * @Author admin
+ * @Description
+ * @Date 2021/7/28 23:37
+ * @Version 0.0.1
+ **/
+public class JsonUtil {
+
+ /**
+ * 对象转json字符串
+ * @param obj
+ * @return
+ */
+ public static String obj2Str(Object obj){
+ return JSONObject.toJSONString(obj);
+ }
+}
diff --git a/oss-common/src/main/java/cn/axzo/oss/common/utils/Utility.java b/oss-common/src/main/java/cn/axzo/oss/common/utils/Utility.java
new file mode 100644
index 0000000..db15d6c
--- /dev/null
+++ b/oss-common/src/main/java/cn/axzo/oss/common/utils/Utility.java
@@ -0,0 +1,128 @@
+package cn.axzo.oss.common.utils;
+
+import cn.axzo.oss.common.enums.FileClassEnum;
+import cn.axzo.oss.common.enums.StorageUnitEnum;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Objects;
+import java.util.UUID;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Hex;
+
+/**
+ * @Author admin
+ * @Description
+ * @Date 2021/7/28 22:54
+ * @Version 0.0.1
+ **/
+
+@Slf4j
+public class Utility {
+
+
+ /**
+ * 判断对象为null
+ * @param obj
+ * @return
+ */
+ public static boolean objIsNull(Object obj){
+ return Objects.isNull(obj);
+ }
+
+ /**
+ * 判断对象不为null
+ * @param obj
+ * @return
+ */
+ public static boolean objIsNotNull(Object obj){
+ return !Objects.isNull(obj);
+ }
+
+ /**
+ * 字符串为空
+ * @return
+ */
+ public static boolean isBlank(String str){
+ int strLen;
+ if (str == null || (strLen = str.length()) == 0){
+ return Boolean.TRUE;
+ }
+ for (int i = 0; i< strLen; i++){
+ if ((Character.isWhitespace(str.charAt(i)) == false)){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 获取md5摘要
+ * @param content
+ * @return
+ */
+ public static String getMd5(String content){
+ if (isBlank(content)){
+ return content;
+ }
+ try {
+ MessageDigest md5 = MessageDigest.getInstance("MD5");
+ md5.reset();
+ md5.update(content.getBytes(StandardCharsets.UTF_8));
+ return Hex.encodeHexString(md5.digest());
+ } catch (NoSuchAlgorithmException e) {
+ log.warn("getMd5 fail = {}",e.getMessage());
+ }
+ return content;
+ }
+
+ /**
+ * 获取文件的MD5值
+ * @param bytes
+ * @return
+ */
+ public static String getMd5(byte [] bytes) {
+ try {
+ MessageDigest md5 = MessageDigest.getInstance("MD5");
+ md5.reset();
+ md5.update(bytes);
+ return Hex.encodeHexString(md5.digest());
+ } catch (NoSuchAlgorithmException e) {
+ log.warn("getMd5 fail = {}",e.getMessage());
+ }
+ return "";
+ }
+
+ /**
+ * 容量换算
+ * @return
+ */
+ public static int capacityConversion(int size, String storageUnit) {
+ StorageUnitEnum storageUnitEnum = StorageUnitEnum.valueOf(storageUnit);
+ if (objIsNull(storageUnitEnum)) {
+ return 0;
+ }
+ return storageUnitEnum.getSize() * size;
+ }
+
+ /**
+ * 生成UUID
+ * @return
+ */
+ public static String getUUID(){
+ return UUID.randomUUID().toString().replaceAll("-","");
+ }
+
+ /**
+ * 生成file key
+ * @return
+ */
+ public static String generateFileKey(String directory, String fileUuid, String fileFormat){
+ StringBuilder tgtFileKey = new StringBuilder(directory);
+ tgtFileKey.append(FileClassEnum.SEPARATOR_CHAR.type);
+ tgtFileKey.append(fileUuid);
+ tgtFileKey.append(FileClassEnum.DOT.type);
+ tgtFileKey.append(fileFormat);
+ return tgtFileKey.toString();
+ }
+}
diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/AppChannelBucketDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/AppChannelBucketDao.java
index d9db5c3..1319b72 100644
--- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/AppChannelBucketDao.java
+++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/AppChannelBucketDao.java
@@ -2,6 +2,7 @@ package cn.axzo.oss.dal.repository;
import cn.axzo.oss.dal.entity.AppChannelBucket;
import com.baomidou.mybatisplus.extension.service.IService;
+import java.util.List;
/**
*
@@ -13,4 +14,11 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface AppChannelBucketDao extends IService {
+ /**
+ * 通过appcode获取文件渠道桶信息
+ *
+ * @param appCode appcode
+ * @return
+ */
+ List getByAppCode(String appCode);
}
diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileAppDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileAppDao.java
index 642606b..7966b48 100644
--- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileAppDao.java
+++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileAppDao.java
@@ -13,4 +13,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface FileAppDao extends IService {
+ /**
+ * 通过appCode获取应用信息
+ * @param appCode
+ * @return
+ */
+ FileApp getByAppCode(String appCode);
}
diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileBusinessSceneDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileBusinessSceneDao.java
index 80078ec..7b2c8ea 100644
--- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileBusinessSceneDao.java
+++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileBusinessSceneDao.java
@@ -13,4 +13,12 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface FileBusinessSceneDao extends IService {
+ /**
+ * 指定appcode文件业务场景
+ *
+ * @param bucketNo 应用编码
+ * @param bizScene
+ * @return
+ */
+ FileBusinessScene getByBucketNoAndScene(String bucketNo, String bizScene);
}
diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileChannelDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileChannelDao.java
index 28cfecd..379a7fb 100644
--- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileChannelDao.java
+++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileChannelDao.java
@@ -2,6 +2,7 @@ package cn.axzo.oss.dal.repository;
import cn.axzo.oss.dal.entity.FileChannel;
import com.baomidou.mybatisplus.extension.service.IService;
+import java.util.List;
/**
*
@@ -13,4 +14,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface FileChannelDao extends IService {
+ /**
+ * 通过channelCode获取最高优化级可用文件渠道
+ * @param channelCodes
+ * @return
+ */
+ List getByChannelCode(List channelCodes);
}
diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileDao.java
index 8da293e..64f0f7b 100644
--- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileDao.java
+++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileDao.java
@@ -13,4 +13,11 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface FileDao extends IService {
+ /**
+ * 根据url md5获取文件信息
+ * @param appCode
+ * @param urlMd5
+ * @return
+ */
+ File getByAppCodeAndUrlMd5(String appCode, String urlMd5);
}
diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileUploadConfigDao.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileUploadConfigDao.java
index 16e9364..7fb886b 100644
--- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileUploadConfigDao.java
+++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/FileUploadConfigDao.java
@@ -13,4 +13,12 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface FileUploadConfigDao extends IService {
+ /**
+ * 通过渠道码和桶名称获取获取指定上传配置
+ *
+ * @param bucketNo
+ * @param directory
+ * @return
+ */
+ FileUploadConfig getByUploadConfig(String bucketNo, String directory);
}
diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/AppChannelBucketDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/AppChannelBucketDaoImpl.java
index d9f2272..1f17e61 100644
--- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/AppChannelBucketDaoImpl.java
+++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/AppChannelBucketDaoImpl.java
@@ -1,9 +1,11 @@
package cn.axzo.oss.dal.repository.impl;
+import cn.axzo.oss.common.enums.IsDeleteEnum;
import cn.axzo.oss.dal.entity.AppChannelBucket;
import cn.axzo.oss.dal.mapper.AppChannelBucketMapper;
import cn.axzo.oss.dal.repository.AppChannelBucketDao;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import java.util.List;
import org.springframework.stereotype.Repository;
/**
@@ -15,6 +17,18 @@ import org.springframework.stereotype.Repository;
* @since 2021-07-23
*/
@Repository("appChannelBucketDao")
-public class AppChannelBucketDaoImpl extends ServiceImpl implements AppChannelBucketDao {
+public class AppChannelBucketDaoImpl extends
+ ServiceImpl implements AppChannelBucketDao {
+ /**
+ * 通过appcode获取文件渠道桶信息
+ *
+ * @param appCode appcode
+ * @return
+ */
+ @Override
+ public List getByAppCode(String appCode) {
+ return lambdaQuery().eq(AppChannelBucket::getAppCode, appCode)
+ .eq(AppChannelBucket::getIsDelete, IsDeleteEnum.NO.getCode()).list();
+ }
}
diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileAppDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileAppDaoImpl.java
index fce99b7..cf3850c 100644
--- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileAppDaoImpl.java
+++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileAppDaoImpl.java
@@ -1,5 +1,6 @@
package cn.axzo.oss.dal.repository.impl;
+import cn.axzo.oss.common.enums.IsDeleteEnum;
import cn.axzo.oss.dal.entity.FileApp;
import cn.axzo.oss.dal.mapper.FileAppMapper;
import cn.axzo.oss.dal.repository.FileAppDao;
@@ -17,4 +18,17 @@ import org.springframework.stereotype.Repository;
@Repository("fileAppDao")
public class FileAppDaoImpl extends ServiceImpl implements FileAppDao {
+
+ /**
+ * 通过appCode获取应用信息
+ *
+ * @param appCode
+ * @return
+ */
+ @Override
+ public FileApp getByAppCode(String appCode) {
+ return lambdaQuery().eq(FileApp::getAppCode, appCode)
+ .eq(FileApp::getStatus, 1)
+ .eq(FileApp::getIsDelete, IsDeleteEnum.NO.getCode()).one();
+ }
}
diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileBusinessSceneDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileBusinessSceneDaoImpl.java
index 9cd9f12..51806ed 100644
--- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileBusinessSceneDaoImpl.java
+++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileBusinessSceneDaoImpl.java
@@ -1,5 +1,6 @@
package cn.axzo.oss.dal.repository.impl;
+import cn.axzo.oss.common.enums.IsDeleteEnum;
import cn.axzo.oss.dal.entity.FileBusinessScene;
import cn.axzo.oss.dal.mapper.FileBusinessSceneMapper;
import cn.axzo.oss.dal.repository.FileBusinessSceneDao;
@@ -15,6 +16,19 @@ import org.springframework.stereotype.Repository;
* @since 2021-07-23
*/
@Repository("fileBusinessSceneDao")
-public class FileBusinessSceneDaoImpl extends ServiceImpl implements FileBusinessSceneDao {
+public class FileBusinessSceneDaoImpl extends
+ ServiceImpl implements FileBusinessSceneDao {
+ /**
+ * 指定appcode文件业务场景
+ *
+ * @param bucketNo
+ * @return
+ */
+ @Override
+ public FileBusinessScene getByBucketNoAndScene(String bucketNo, String bizScen) {
+ return lambdaQuery().eq(FileBusinessScene::getAppChannelBucketNo, bucketNo)
+ .eq(FileBusinessScene::getBusinessScene,bizScen)
+ .eq(FileBusinessScene::getIsDelete, IsDeleteEnum.NO.getCode()).one();
+ }
}
diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileChannelDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileChannelDaoImpl.java
index 558d91d..6458b3a 100644
--- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileChannelDaoImpl.java
+++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileChannelDaoImpl.java
@@ -4,6 +4,7 @@ import cn.axzo.oss.dal.entity.FileChannel;
import cn.axzo.oss.dal.mapper.FileChannelMapper;
import cn.axzo.oss.dal.repository.FileChannelDao;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import java.util.List;
import org.springframework.stereotype.Repository;
/**
@@ -17,4 +18,16 @@ import org.springframework.stereotype.Repository;
@Repository("fileChannelDao")
public class FileChannelDaoImpl extends ServiceImpl implements FileChannelDao {
+ /**
+ * 通过channelCode获取多个可用文件渠道
+ *
+ * @param channelCodes
+ * @return
+ */
+ @Override
+ public List getByChannelCode(List channelCodes) {
+ return lambdaQuery().in(FileChannel::getChannelCode,channelCodes)
+ .eq(FileChannel::getStatus,1)
+ .orderByAsc(FileChannel::getPriority).list();
+ }
}
diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileDaoImpl.java
index 83924b6..c6da68c 100644
--- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileDaoImpl.java
+++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileDaoImpl.java
@@ -1,5 +1,7 @@
package cn.axzo.oss.dal.repository.impl;
+import cn.axzo.oss.common.constans.CommonConstants.FileStatus;
+import cn.axzo.oss.common.constans.CommonConstants.TableDelete;
import cn.axzo.oss.dal.entity.File;
import cn.axzo.oss.dal.mapper.FileMapper;
import cn.axzo.oss.dal.repository.FileDao;
@@ -17,4 +19,10 @@ import org.springframework.stereotype.Repository;
@Repository("fileDao")
public class FileDaoImpl extends ServiceImpl implements FileDao {
+ @Override
+ public File getByAppCodeAndUrlMd5(String appCode, String urlMd5) {
+ return lambdaQuery().eq(File::getAppCode, appCode).eq(File::getUrlMd5, urlMd5)
+ .eq(File::getStatus, FileStatus.SUCCESS).eq(File::getIsDelete, TableDelete.UN_DELETED)
+ .last("limit 1").one();
+ }
}
diff --git a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileUploadConfigDaoImpl.java b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileUploadConfigDaoImpl.java
index 24f506a..9557cff 100644
--- a/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileUploadConfigDaoImpl.java
+++ b/oss-dal/src/main/java/cn/axzo/oss/dal/repository/impl/FileUploadConfigDaoImpl.java
@@ -1,5 +1,6 @@
package cn.axzo.oss.dal.repository.impl;
+import cn.axzo.oss.common.enums.IsDeleteEnum;
import cn.axzo.oss.dal.entity.FileUploadConfig;
import cn.axzo.oss.dal.mapper.FileUploadConfigMapper;
import cn.axzo.oss.dal.repository.FileUploadConfigDao;
@@ -15,6 +16,20 @@ import org.springframework.stereotype.Repository;
* @since 2021-07-23
*/
@Repository("fileUploadConfigDao")
-public class FileUploadConfigDaoImpl extends ServiceImpl implements FileUploadConfigDao {
+public class FileUploadConfigDaoImpl extends
+ ServiceImpl implements FileUploadConfigDao {
+ /**
+ * 通过渠道码和桶名称获取获取指定上传配置
+ *
+ * @param bucketNo
+ * @param directory
+ * @return
+ */
+ @Override
+ public FileUploadConfig getByUploadConfig(String bucketNo, String directory) {
+ return lambdaQuery().eq(FileUploadConfig::getAppChannelBucketNo, bucketNo)
+ .eq(FileUploadConfig::getDirectory, directory)
+ .eq(FileUploadConfig::getIsDelete, IsDeleteEnum.NO.getCode()).one();
+ }
}
diff --git a/oss-http-api/src/main/java/cn/axzo/oss/http/api/ServerFileServiceApi.java b/oss-http-api/src/main/java/cn/axzo/oss/http/api/ServerFileServiceApi.java
index 133b504..ec590f9 100644
--- a/oss-http-api/src/main/java/cn/axzo/oss/http/api/ServerFileServiceApi.java
+++ b/oss-http-api/src/main/java/cn/axzo/oss/http/api/ServerFileServiceApi.java
@@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
*/
@FeignClient(
name = "oss",
- url = "http://oss"
+ url = "http://oss:9123"
)
@RequestMapping(value = "/api/v1/server")
public interface ServerFileServiceApi {
diff --git a/oss-http-api/src/main/java/cn/axzo/oss/http/model/ServerFileDeleteRequest.java b/oss-http-api/src/main/java/cn/axzo/oss/http/model/ServerFileDeleteRequest.java
index 7bc9314..d789bcf 100644
--- a/oss-http-api/src/main/java/cn/axzo/oss/http/model/ServerFileDeleteRequest.java
+++ b/oss-http-api/src/main/java/cn/axzo/oss/http/model/ServerFileDeleteRequest.java
@@ -14,7 +14,13 @@ import javax.validation.constraints.NotBlank;
@Data
public class ServerFileDeleteRequest {
+ @NotBlank(message = "appCode must not be null")
+ private String appCode;
+
@NotBlank(message = "url must not be null")
private String url;
+ @NotBlank(message = "operator must not be null")
+ private String operator;
+
}
diff --git a/oss-integration/pom.xml b/oss-integration/pom.xml
index 969c205..28db6e2 100644
--- a/oss-integration/pom.xml
+++ b/oss-integration/pom.xml
@@ -19,7 +19,11 @@
org.springframework.cloud
spring-cloud-starter-openfeign
-
+
+ com.aliyun.oss
+ aliyun-sdk-oss
+
+
diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/AliOssService.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/AliOssService.java
new file mode 100644
index 0000000..8808762
--- /dev/null
+++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/AliOssService.java
@@ -0,0 +1,13 @@
+package cn.axzo.oss.integration.s3;
+
+import cn.axzo.oss.integration.s3.base.BaseS3Service;
+
+/**
+ * @program: oss
+ * @description: 阿里云oss服务
+ * @author: mr.jie
+ * @date: 2021-07-29 15:44
+ **/
+public interface AliOssService extends BaseS3Service {
+
+}
diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/base/BaseS3Service.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/base/BaseS3Service.java
new file mode 100644
index 0000000..06639bf
--- /dev/null
+++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/base/BaseS3Service.java
@@ -0,0 +1,55 @@
+package cn.axzo.oss.integration.s3.base;
+
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @Author admin
+ * @Description
+ * @Date 2021/7/28 23:46
+ * @Version 0.0.1
+ **/
+public interface BaseS3Service {
+
+ int RECORD_LIMIT = 100;
+ // ttl 15m; 60 * 15 = 900s
+ int DEFAULT_TTL_S = 900;
+
+ /**
+ * upload file
+ */
+ String uploadByStream(String bucketName, String tgtFileKey, InputStream srcStream);
+
+ /**
+ * upload multi file
+ */
+ boolean uploadMultiFile(MultipartFile[] multipartFiles);
+
+ /**
+ * delete file
+ */
+ boolean delFile(String bucket, String tgtFileKey);
+
+
+ /**
+ * download file
+ */
+ ResponseEntity download(String tgtFileKey);
+
+ /**
+ * get file address
+ *
+ * @param ttl second
+ */
+ String getFileAddress(String tgtFileKey, int ttl);
+
+ /**
+ * get S3Object stream
+ */
+ FilterInputStream getS3ObjectStream(String tgtFileKey);
+
+
+
+}
diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/base/OssClientBase.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/base/OssClientBase.java
new file mode 100644
index 0000000..97b9020
--- /dev/null
+++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/base/OssClientBase.java
@@ -0,0 +1,17 @@
+package cn.axzo.oss.integration.s3.base;
+
+/**
+ * @program: oss
+ * @description: 客户端接口
+ * @author: mr.jie
+ * @date: 2021-07-29 18:07
+ **/
+public interface OssClientBase {
+
+ Object getClient();
+
+ void initClient();
+
+ String getEndpoint();
+
+}
diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/client/AliOssClient.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/client/AliOssClient.java
new file mode 100644
index 0000000..ce5911a
--- /dev/null
+++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/client/AliOssClient.java
@@ -0,0 +1,55 @@
+package cn.axzo.oss.integration.s3.client;
+
+
+import cn.axzo.oss.common.enums.CodeEnum;
+import cn.axzo.oss.common.exception.S3Exception;
+import cn.axzo.oss.common.utils.Utility;
+import cn.axzo.oss.integration.s3.base.OssClientBase;
+import cn.axzo.oss.integration.s3.config.AliOssConfig;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import javax.annotation.PostConstruct;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @program: oss
+ * @description: 阿里云服务客户端
+ * @author: mr.jie
+ * @date: 2021-07-29 15:49
+ **/
+@Component
+@Slf4j
+public class AliOssClient implements OssClientBase {
+ private volatile static OSS instance = null;
+
+ @Autowired
+ private AliOssConfig aliOssConfig;
+
+ public OSS getClient(){
+ if (Utility.objIsNull(instance)){
+ throw new S3Exception(CodeEnum.S3_CLIENT_NULL.getCode(),"oss客户端未初始化");
+ }
+ return instance;
+ }
+
+
+ @PostConstruct
+ @Override
+ public void initClient(){
+ log.info("initClient endpoint = {}, accessKeyId = {},secretAccessKey = {}", aliOssConfig.getEndpoint(),aliOssConfig.getAccessKeyId(),aliOssConfig.getSecretAccessKey());
+ try {
+ instance = new OSSClientBuilder().build(aliOssConfig.getEndpoint(),aliOssConfig.getAccessKeyId(),aliOssConfig.getSecretAccessKey());
+ } catch (Exception e) {
+ instance = null;
+ log.error("initClient error = {}", e);
+ }
+ }
+
+ @Override
+ public String getEndpoint(){
+ return aliOssConfig.getEndpoint();
+ }
+
+}
diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/config/AliOssConfig.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/config/AliOssConfig.java
new file mode 100644
index 0000000..8851f93
--- /dev/null
+++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/config/AliOssConfig.java
@@ -0,0 +1,35 @@
+package cn.axzo.oss.integration.s3.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * @program: oss
+ * @description: 阿里云配置
+ * @author: mr.jie
+ * @date: 2021-07-29 17:57
+ **/
+@Component
+public class AliOssConfig {
+
+ @Value("${aliyun.oss.accessKeyId}")
+ private String ACCESS_KEY_ID;
+
+ @Value("${aliyun.oss.secretAccessKey}")
+ private String SECRET_ACCESS_KEY;
+
+ @Value("${aliyun.oss.endpoint}")
+ private String ENDPOINT;
+
+ public String getAccessKeyId(){
+ return this.ACCESS_KEY_ID;
+ }
+
+ public String getSecretAccessKey(){
+ return this.SECRET_ACCESS_KEY;
+ }
+
+ public String getEndpoint(){
+ return this.ENDPOINT;
+ }
+}
diff --git a/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/AliOssServiceImpl.java b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/AliOssServiceImpl.java
new file mode 100644
index 0000000..57821c9
--- /dev/null
+++ b/oss-integration/src/main/java/cn/axzo/oss/integration/s3/impl/AliOssServiceImpl.java
@@ -0,0 +1,103 @@
+package cn.axzo.oss.integration.s3.impl;
+
+import cn.axzo.oss.integration.s3.AliOssService;
+import cn.axzo.oss.integration.s3.client.AliOssClient;
+import com.aliyun.oss.ClientException;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSException;
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * @program: oss
+ * @description: 阿里oss服务
+ * @author: mr.jie
+ * @date: 2021-07-29 15:45
+ **/
+@Service
+@Slf4j
+public class AliOssServiceImpl implements AliOssService {
+
+ @Autowired
+ private AliOssClient aliOssClient;
+
+ /**
+ * upload file
+ */
+ @Override
+ public String uploadByStream(String bucketName, String tgtFileKey, InputStream srcStream) {
+ OSS client = aliOssClient.getClient();
+ try {
+ client.putObject(bucketName, tgtFileKey, srcStream);
+ } catch (OSSException e) {
+ log.error("uploadByStream OSSException", e);
+ return "";
+ } catch (ClientException e) {
+ log.error("uploadByStream ClientException", e);
+ return "";
+ }
+
+ StringBuilder allBuilder = new StringBuilder();
+ allBuilder.append("https://");
+ allBuilder.append(bucketName);
+ allBuilder.append(".");
+ allBuilder.append(aliOssClient.getEndpoint());
+ allBuilder.append(tgtFileKey);
+
+ return allBuilder.toString();
+ }
+
+ /**
+ * upload multi file
+ */
+ @Override
+ public boolean uploadMultiFile(MultipartFile[] multipartFiles) {
+ return false;
+ }
+
+ /**
+ * delete file
+ */
+ @Override
+ public boolean delFile(String bucket, String tgtFileKey) {
+ log.debug("ali oss delFile bucket = {}, tatFileKey = {}", bucket, tgtFileKey);
+ try {
+ aliOssClient.getClient().deleteObject(bucket, tgtFileKey);
+ return Boolean.TRUE;
+ } catch (Exception e) {
+ log.error("ali oss delFile error = {}", e);
+ }
+ return Boolean.FALSE;
+ }
+
+ /**
+ * download file
+ */
+ @Override
+ public ResponseEntity download(String tgtFileKey) {
+ return null;
+ }
+
+ /**
+ * get file address
+ *
+ * @param ttl second
+ */
+ @Override
+ public String getFileAddress(String tgtFileKey, int ttl) {
+ return null;
+ }
+
+ /**
+ * get S3Object stream
+ */
+ @Override
+ public FilterInputStream getS3ObjectStream(String tgtFileKey) {
+ return null;
+ }
+}
diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/AppChannelBucketManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/AppChannelBucketManager.java
new file mode 100644
index 0000000..00d1b7b
--- /dev/null
+++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/AppChannelBucketManager.java
@@ -0,0 +1,20 @@
+package cn.axzo.oss.manager.api;
+
+import cn.axzo.oss.dal.entity.AppChannelBucket;
+import java.util.List;
+
+/**
+ * @author: zhangran
+ * @date: 20210803 15:30
+ * @description:
+ **/
+public interface AppChannelBucketManager {
+
+ /**
+ * 通过appcode获取文件渠道桶信息
+ *
+ * @param appCode appcode
+ * @return
+ */
+ AppChannelBucket getByAppCode(String appCode);
+}
diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileAppManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileAppManager.java
new file mode 100644
index 0000000..01a16ff
--- /dev/null
+++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileAppManager.java
@@ -0,0 +1,21 @@
+package cn.axzo.oss.manager.api;
+
+import cn.axzo.oss.dal.entity.FileApp;
+
+/**
+ * @author: zhangran
+ * @date: 20210803 15:28
+ * @description:
+ **/
+public interface FileAppManager {
+
+ /**
+ * 通过appCode获取应用信息
+ *
+ * @param appCode
+ * @return
+ */
+ FileApp getByAppCode(String appCode);
+
+
+}
diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileBusinessSceneManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileBusinessSceneManager.java
new file mode 100644
index 0000000..772b09e
--- /dev/null
+++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileBusinessSceneManager.java
@@ -0,0 +1,20 @@
+package cn.axzo.oss.manager.api;
+
+import cn.axzo.oss.dal.entity.FileBusinessScene;
+
+/**
+ * @author: zhangran
+ * @date: 20210803 15:42
+ * @description:
+ **/
+public interface FileBusinessSceneManager {
+
+ /**
+ * 指定appcode文件业务场景
+ *
+ * @param bucketNo 应用编码
+ * @param bizScene
+ * @return
+ */
+ FileBusinessScene getByBucketNoAndScene(String bucketNo,String bizScene);
+}
diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileChannelManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileChannelManager.java
new file mode 100644
index 0000000..be1a250
--- /dev/null
+++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileChannelManager.java
@@ -0,0 +1,29 @@
+package cn.axzo.oss.manager.api;
+
+import cn.axzo.oss.dal.entity.AppChannelBucket;
+import cn.axzo.oss.dal.entity.FileChannel;
+import java.util.List;
+
+/**
+ * @author: zhangran
+ * @date: 20210803 15:33
+ * @description:
+ **/
+public interface FileChannelManager {
+
+ /**
+ * 返回所有渠道 按优先级升序返回
+ *
+ * @param channelCodes
+ * @return
+ */
+ List listChannelCodeOrderByPriorityAsc(List channelCodes);
+
+ /**
+ * 返回一个最优的渠道 升序第一个
+ *
+ * @param appChannelBuckets
+ * @return
+ */
+ FileChannel getOptimalChannel(List appChannelBuckets );
+}
diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileManager.java
new file mode 100644
index 0000000..b5355ea
--- /dev/null
+++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileManager.java
@@ -0,0 +1,29 @@
+package cn.axzo.oss.manager.api;
+
+/**
+ * @Author admin
+ * @Description
+ * @Date 2021/7/28 22:48
+ * @Version 0.0.1
+ **/
+public interface FileManager {
+
+ /**
+ * 删除文件
+ * @param bucketName 桶名称
+ * @param tgtFileKey 目标文件key
+ * @return
+ */
+ boolean delete(String bucketName, String tgtFileKey);
+
+ /**
+ * 上传
+ *
+ * @param bulkName
+ * @param keyPath
+ * @param fileContent
+ * @return
+ */
+ String uploadByStream(String bulkName, String keyPath, byte[] fileContent);
+
+}
diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileUploadConfigManager.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileUploadConfigManager.java
new file mode 100644
index 0000000..e3229fc
--- /dev/null
+++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/FileUploadConfigManager.java
@@ -0,0 +1,20 @@
+package cn.axzo.oss.manager.api;
+
+import cn.axzo.oss.dal.entity.FileUploadConfig;
+
+/**
+ * @author: zhangran
+ * @date: 20210803 15:43
+ * @description:
+ **/
+public interface FileUploadConfigManager {
+
+ /**
+ * 通过渠道码和桶名称获取获取指定上传配置
+ *
+ * @param bucketNo
+ * @param directory
+ * @return
+ */
+ FileUploadConfig getByUploadConfig(String bucketNo, String directory);
+}
diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/ServerFileDeleteDto.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/ServerFileDeleteDto.java
new file mode 100644
index 0000000..1bc1ed7
--- /dev/null
+++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/ServerFileDeleteDto.java
@@ -0,0 +1,26 @@
+package cn.axzo.oss.manager.api.dto.request;
+
+import lombok.Data;
+
+/**
+ * @Author admin
+ * @Description
+ * @Date 2021/7/28 22:50
+ * @Version 0.0.1
+ **/
+@Data
+public class ServerFileDeleteDto {
+
+ /**
+ * 应用码
+ */
+ private String appCode;
+ /**
+ * 文件地址
+ */
+ private String url;
+ /**
+ * 操作人
+ */
+ private String operator;
+}
diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/ServerFileUploadDto.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/ServerFileUploadDto.java
new file mode 100644
index 0000000..c290db6
--- /dev/null
+++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/request/ServerFileUploadDto.java
@@ -0,0 +1,19 @@
+package cn.axzo.oss.manager.api.dto.request;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * @program: oss
+ * @description: 文件上传
+ * @author: mr.jie
+ * @date: 2021-07-29 18:31
+ **/
+@Data
+public class ServerFileUploadDto {
+ private String appCode;
+ private String bizScene;
+ private String fileName;
+ private byte[] fileContent;
+}
diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/ServerFileDeleteResponse.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/ServerFileDeleteResponse.java
new file mode 100644
index 0000000..83b4ee5
--- /dev/null
+++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/ServerFileDeleteResponse.java
@@ -0,0 +1,11 @@
+package cn.axzo.oss.manager.api.dto.response;
+
+/**
+ * @Author admin
+ * @Description
+ * @Date 2021/7/28 22:51
+ * @Version 0.0.1
+ **/
+public class ServerFileDeleteResponse {
+
+}
diff --git a/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/ServerFileUploadResponse.java b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/ServerFileUploadResponse.java
new file mode 100644
index 0000000..3f981ae
--- /dev/null
+++ b/oss-manager-api/src/main/java/cn/axzo/oss/manager/api/dto/response/ServerFileUploadResponse.java
@@ -0,0 +1,28 @@
+package cn.axzo.oss.manager.api.dto.response;
+
+import lombok.Data;
+
+/**
+ * 服务端文件上传响应类
+ *
+ * @author zhaoyong
+ * @see ServerFileUploadResponse
+ * @since 2021-07-23 10:37
+ */
+@Data
+public class ServerFileUploadResponse {
+
+ /**
+ * 文件 URL
+ */
+ private String url;
+ /**
+ * 文件 Key
+ */
+ private String fileKey;
+ /**
+ * URL MD5
+ */
+ private String urlMd5;
+
+}
diff --git a/oss-manager/src/main/java/cn/axzo/oss/manager/impl/AppChannelBucketManagerImpl.java b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/AppChannelBucketManagerImpl.java
new file mode 100644
index 0000000..0e2b155
--- /dev/null
+++ b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/AppChannelBucketManagerImpl.java
@@ -0,0 +1,51 @@
+package cn.axzo.oss.manager.impl;
+
+import cn.axzo.oss.common.enums.CodeEnum;
+import cn.axzo.oss.common.exception.BizException;
+import cn.axzo.oss.dal.entity.AppChannelBucket;
+import cn.axzo.oss.dal.entity.FileChannel;
+import cn.axzo.oss.dal.repository.AppChannelBucketDao;
+import cn.axzo.oss.manager.api.AppChannelBucketManager;
+import cn.axzo.oss.manager.api.FileChannelManager;
+import java.util.List;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author: zhangran
+ * @date: 20210803 15:44
+ * @description:
+ **/
+@Service
+@Slf4j
+public class AppChannelBucketManagerImpl implements AppChannelBucketManager {
+
+ @Autowired
+ private AppChannelBucketDao appChannelBucketDao;
+
+ @Autowired
+ private FileChannelManager fileChannelManager;
+
+ /**
+ * 通过appcode获取文件渠道桶信息
+ *
+ * @param appCode appcode
+ * @return
+ */
+ @Override
+ public AppChannelBucket getByAppCode(String appCode) {
+ List appChannelBuckets = appChannelBucketDao.getByAppCode(appCode);
+ BizException.isEmpty(appChannelBuckets, CodeEnum.APP_CHANNEL_BUCKET_NOT_FOUND);
+
+ // 找到最优渠道
+ FileChannel fileChannel = fileChannelManager.getOptimalChannel(appChannelBuckets);
+
+ AppChannelBucket appChannelBucket = appChannelBuckets.stream().filter(bucket ->
+ bucket.getChannelCode().equals(fileChannel.getChannelCode()))
+ .findFirst().orElse(null);
+ BizException.isEmpty(appChannelBucket, CodeEnum.APP_CHANNEL_NOT_FOUND);
+
+ return appChannelBucket;
+ }
+}
diff --git a/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileBusinessSceneManagerImpl.java b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileBusinessSceneManagerImpl.java
new file mode 100644
index 0000000..7e542ce
--- /dev/null
+++ b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileBusinessSceneManagerImpl.java
@@ -0,0 +1,38 @@
+package cn.axzo.oss.manager.impl;
+
+import cn.axzo.oss.common.enums.CodeEnum;
+import cn.axzo.oss.common.exception.BizException;
+import cn.axzo.oss.dal.entity.FileBusinessScene;
+import cn.axzo.oss.dal.repository.FileBusinessSceneDao;
+import cn.axzo.oss.manager.api.FileBusinessSceneManager;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author: zhangran
+ * @date: 20210803 16:36
+ * @description:
+ **/
+@Service
+@Slf4j
+public class FileBusinessSceneManagerImpl implements FileBusinessSceneManager {
+
+ @Autowired
+ private FileBusinessSceneDao fileBusinessSceneDao;
+
+ /**
+ * 指定appcode文件业务场景
+ *
+ * @param bucketNo 应用编码
+ * @param bizScene
+ * @return
+ */
+ @Override
+ public FileBusinessScene getByBucketNoAndScene(String bucketNo, String bizScene) {
+ FileBusinessScene fileBusinessScene = fileBusinessSceneDao
+ .getByBucketNoAndScene(bucketNo, bizScene);
+ BizException.isEmpty(fileBusinessScene, CodeEnum.APP_CHANNEL_NOT_FOUND);
+ return fileBusinessScene;
+ }
+}
diff --git a/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileChannelManagerImpl.java b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileChannelManagerImpl.java
new file mode 100644
index 0000000..529d680
--- /dev/null
+++ b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileChannelManagerImpl.java
@@ -0,0 +1,56 @@
+package cn.axzo.oss.manager.impl;
+
+import cn.axzo.oss.common.enums.CodeEnum;
+import cn.axzo.oss.common.exception.BizException;
+import cn.axzo.oss.dal.entity.AppChannelBucket;
+import cn.axzo.oss.dal.entity.FileChannel;
+import cn.axzo.oss.dal.repository.FileChannelDao;
+import cn.axzo.oss.manager.api.FileChannelManager;
+import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.List;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author: zhangran
+ * @date: 20210803 16:28
+ * @description:
+ **/
+@Service
+@Slf4j
+public class FileChannelManagerImpl implements FileChannelManager {
+
+ @Autowired
+ private FileChannelDao fileChannelDao;
+
+ /**
+ * 返回所有渠道 按优先级升序返回
+ *
+ * @param channelCodes
+ * @return
+ */
+ @Override
+ public List listChannelCodeOrderByPriorityAsc(List channelCodes) {
+ List fileChannels = fileChannelDao.getByChannelCode(channelCodes);
+ BizException.isEmpty(fileChannels, CodeEnum.APP_CHANNEL_NOT_FOUND);
+ return fileChannels;
+ }
+
+ /**
+ * 返回一个最优的渠道 升序第一个
+ *
+ * @param appChannelBuckets
+ * @return
+ */
+ @Override
+ public FileChannel getOptimalChannel(List appChannelBuckets ) {
+ ArrayList channels = Lists.newArrayList();
+ appChannelBuckets.forEach(appChannelBucket -> channels.add(appChannelBucket.getChannelCode()));
+
+ List fileChannels = fileChannelDao.getByChannelCode(channels);
+ BizException.isEmpty(fileChannels, CodeEnum.APP_CHANNEL_NOT_FOUND);
+ return fileChannels.get(0);
+ }
+}
diff --git a/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileManagerImpl.java b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileManagerImpl.java
new file mode 100644
index 0000000..45bf80b
--- /dev/null
+++ b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileManagerImpl.java
@@ -0,0 +1,46 @@
+package cn.axzo.oss.manager.impl;
+
+import cn.axzo.oss.integration.s3.AliOssService;
+import cn.axzo.oss.manager.api.FileManager;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @Author admin
+ * @Description
+ * @Date 2021/7/28 22:48
+ * @Version 0.0.1
+ **/
+@Service
+@Slf4j
+public class FileManagerImpl implements FileManager {
+
+ @Autowired
+ private AliOssService aliOssService;
+
+ /**
+ * 删除文件
+ * @param bucketName 桶名称
+ * @param tgtFileKey 目标文件key
+ * @return
+ */
+ @Override
+ public boolean delete(String bucketName, String tgtFileKey) {
+ return aliOssService.delFile(bucketName, tgtFileKey);
+ }
+
+ /**
+ * @param bulkName 默认的取值为
+ * @param keyPath key的前置路径
+ */
+ public String uploadByStream(String bulkName, String keyPath, byte[] fileContent) {
+
+ InputStream inputStream = new ByteArrayInputStream(fileContent);
+
+ return aliOssService.uploadByStream(bulkName, keyPath, inputStream);
+ }
+
+}
diff --git a/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileUploadConfigManagerImpl.java b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileUploadConfigManagerImpl.java
new file mode 100644
index 0000000..9b8f94b
--- /dev/null
+++ b/oss-manager/src/main/java/cn/axzo/oss/manager/impl/FileUploadConfigManagerImpl.java
@@ -0,0 +1,37 @@
+package cn.axzo.oss.manager.impl;
+
+import cn.axzo.oss.common.enums.CodeEnum;
+import cn.axzo.oss.common.exception.BizException;
+import cn.axzo.oss.dal.entity.FileUploadConfig;
+import cn.axzo.oss.dal.repository.FileUploadConfigDao;
+import cn.axzo.oss.manager.api.FileUploadConfigManager;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author: zhangran
+ * @date: 20210803 16:39
+ * @description:
+ **/
+@Service
+@Slf4j
+public class FileUploadConfigManagerImpl implements FileUploadConfigManager {
+
+ @Autowired
+ private FileUploadConfigDao fileUploadConfigDao;
+
+ /**
+ * 通过渠道码和桶名称获取获取指定上传配置
+ *
+ * @param bucketNo
+ * @param directory
+ * @return
+ */
+ @Override
+ public FileUploadConfig getByUploadConfig(String bucketNo, String directory) {
+ FileUploadConfig uploadConfig = fileUploadConfigDao.getByUploadConfig(bucketNo, directory);
+ BizException.isEmpty(uploadConfig, CodeEnum.NO_UPLOAD_CONFIG);
+ return uploadConfig;
+ }
+}
diff --git a/oss-service-api/src/main/java/cn/axzo/oss/service/api/FileService.java b/oss-service-api/src/main/java/cn/axzo/oss/service/api/FileService.java
new file mode 100644
index 0000000..fafed85
--- /dev/null
+++ b/oss-service-api/src/main/java/cn/axzo/oss/service/api/FileService.java
@@ -0,0 +1,28 @@
+package cn.axzo.oss.service.api;
+
+import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto;
+import cn.axzo.oss.manager.api.dto.request.ServerFileUploadDto;
+import cn.axzo.oss.manager.api.dto.response.ServerFileUploadResponse;
+
+/**
+ * @Author admin
+ * @Description
+ * @Date 2021/7/28 22:48
+ * @Version 0.0.1
+ **/
+public interface FileService {
+
+ /**
+ * 删除文件
+ *
+ * @param dto
+ */
+ void delete(ServerFileDeleteDto dto);
+
+ /**
+ * 上传
+ *
+ * @param request
+ */
+ ServerFileUploadResponse upload(ServerFileUploadDto request);
+}
diff --git a/oss-service/src/main/java/cn/axzo/oss/service/impl/FileServiceImpl.java b/oss-service/src/main/java/cn/axzo/oss/service/impl/FileServiceImpl.java
new file mode 100644
index 0000000..f290b25
--- /dev/null
+++ b/oss-service/src/main/java/cn/axzo/oss/service/impl/FileServiceImpl.java
@@ -0,0 +1,204 @@
+package cn.axzo.oss.service.impl;
+
+import cn.axzo.oss.common.constans.CommonConstants;
+import cn.axzo.oss.common.constans.CommonConstants.FileStatus;
+import cn.axzo.oss.common.constans.CommonConstants.TableDelete;
+import cn.axzo.oss.common.enums.CodeEnum;
+import cn.axzo.oss.common.enums.FileClassEnum;
+import cn.axzo.oss.common.enums.FileStatusEnum;
+import cn.axzo.oss.common.exception.BizException;
+import cn.axzo.oss.common.utils.JsonUtil;
+import cn.axzo.oss.common.utils.Utility;
+import cn.axzo.oss.dal.entity.AppChannelBucket;
+import cn.axzo.oss.dal.entity.File;
+import cn.axzo.oss.dal.entity.FileApp;
+import cn.axzo.oss.dal.entity.FileBusinessScene;
+import cn.axzo.oss.dal.entity.FileUploadConfig;
+import cn.axzo.oss.dal.repository.FileAppDao;
+import cn.axzo.oss.dal.repository.FileDao;
+import cn.axzo.oss.manager.api.AppChannelBucketManager;
+import cn.axzo.oss.manager.api.FileBusinessSceneManager;
+import cn.axzo.oss.manager.api.FileManager;
+import cn.axzo.oss.manager.api.FileUploadConfigManager;
+import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto;
+import cn.axzo.oss.manager.api.dto.request.ServerFileUploadDto;
+import cn.axzo.oss.manager.api.dto.response.ServerFileUploadResponse;
+import cn.axzo.oss.service.api.FileService;
+import java.util.Arrays;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @Author admin
+ * @Description
+ * @Date 2021/7/28 22:48
+ * @Version 0.0.1
+ **/
+@Service
+@Slf4j
+public class FileServiceImpl implements FileService {
+
+ @Autowired
+ private FileManager fileManager;
+
+ @Autowired
+ private FileDao fileDao;
+
+ @Autowired
+ private FileAppDao fileAppDao;
+ @Autowired
+ private AppChannelBucketManager appChannelBucketManager;
+ @Autowired
+ private FileBusinessSceneManager fileBusinessSceneManager;
+ @Autowired
+ private FileUploadConfigManager fileUploadConfigManager;
+
+
+ /**
+ * 删除文件
+ *
+ * @param dto
+ */
+ @Override
+ public void delete(ServerFileDeleteDto dto) {
+ log.info("delete dto = {}", JsonUtil.obj2Str(dto));
+ // 检查app code
+ checkAppCode(dto.getAppCode());
+
+ String urlMd5 = Utility.getMd5(dto.getUrl());
+ log.info("delete urlMd5 = {}", urlMd5);
+
+ File file = fileDao.getByAppCodeAndUrlMd5(dto.getAppCode(), urlMd5);
+ if (Utility.objIsNull(file)) {
+ log.warn("delete file is null,url = {}, urlMd5 = {}", dto.getUrl(), urlMd5);
+ return;
+ }
+ String tgtFileKey = Utility
+ .generateFileKey(file.getDirectory(), file.getFileUuid(), file.getFileFormat());
+ log.debug("delete tgtFileKey = {}", tgtFileKey);
+ boolean deleteFlag = fileManager.delete(file.getBucketName(), tgtFileKey);
+ log.info("delete deleteFlag = {}", deleteFlag);
+ if (deleteFlag) {
+ File updateFile = new File();
+ updateFile.setIsDelete(TableDelete.DELETED);
+ updateFile.setStatus(FileStatus.DELETED);
+ updateFile.setUpdateBy(dto.getOperator());
+ updateFile.setId(file.getId());
+ fileDao.updateById(updateFile);
+ }
+ }
+
+
+ /**
+ * 检查appCode是否有效
+ *
+ * @param appCode
+ */
+ private void checkAppCode(final String appCode) {
+ log.info("checkAppCode appCode = {}", appCode);
+ FileApp fileApp = fileAppDao.getByAppCode(appCode);
+ BizException.error(Utility.objIsNotNull(fileApp), CodeEnum.APP_CODE_NOT_FOUND);
+ }
+
+ /**
+ * 上传
+ *
+ * @param dto
+ */
+ @Override
+ public ServerFileUploadResponse upload(ServerFileUploadDto dto) {
+ log.info("update fileName:{},appCode:{},bizScene:{}",
+ dto.getFileName(), dto.getAppCode(), dto.getBizScene());
+ // 检查appCode
+ checkAppCode(dto.getAppCode());
+
+ // 通过appcode获取文件渠道桶信息
+ AppChannelBucket appChannelBucket = appChannelBucketManager.getByAppCode(dto.getAppCode());
+
+ // 通过渠道桶编码获取到具体文件业务场景
+ FileBusinessScene scene = fileBusinessSceneManager
+ .getByBucketNoAndScene(appChannelBucket.getAppChannelBucketNo(), dto.getBizScene());
+
+ // 通过渠道码和桶名称获取获取指定上传配置
+ FileUploadConfig fileUploadConfig = fileUploadConfigManager
+ .getByUploadConfig(scene.getAppChannelBucketNo(), scene.getDirectory());
+
+ // 上传文件并生成file对象
+ File ossFile = generateFile(fileUploadConfig, dto);
+
+ return setResponse(ossFile);
+ }
+
+ /**
+ * 判断文件是否符合要求
+ */
+ private String isFileConform(FileUploadConfig fileUploadConfig, int fileLength, String fileName) {
+ // 文件大小超出上限
+ int size = Utility
+ .capacityConversion(fileUploadConfig.getStorageSize(), fileUploadConfig.getStorageUnit());
+ BizException.error(size > fileLength, CodeEnum.FILE_SIZE_EXCEEDS_LIMIT);
+ // 文件格式判断
+ String[] formats = fileUploadConfig.getFileFormat().split(FileClassEnum.COMMA.type);
+
+ int lastIndexOf = fileName.lastIndexOf(FileClassEnum.DOT.type);
+ BizException
+ .error(lastIndexOf != CommonConstants.NOT_FOUND_INDEX_OF, CodeEnum.NOT_FILE_FORMAT);
+
+ // 是否包含指定格式
+ String fileFormat = fileName.substring(lastIndexOf + CommonConstants.ONE).toLowerCase();
+ boolean contains = Arrays.asList(formats).contains(fileFormat);
+ BizException.error(contains, CodeEnum.FILE_FORMAT_NOT_SUPPORTED);
+
+ return fileFormat;
+ }
+
+ private File generateFile(FileUploadConfig fileUploadConfig, ServerFileUploadDto dto) {
+ // 判断容量
+ String fileConform = isFileConform(fileUploadConfig, dto.getFileContent().length,
+ dto.getFileName());
+
+ String uuid = Utility.getUUID();
+
+ // 生成上传文件的唯一key
+ String tgtFileKey = Utility.generateFileKey(fileUploadConfig.getDirectory(), uuid, fileConform);
+
+ File ossFile = new File();
+ ossFile.setAppChannelBucketNo(fileUploadConfig.getAppChannelBucketNo());
+ ossFile.setAppCode(fileUploadConfig.getAppCode());
+ ossFile.setChannelCode(fileUploadConfig.getChannelCode());
+ ossFile.setBucketName(fileUploadConfig.getBucketName());
+ ossFile.setDirectory(fileUploadConfig.getDirectory());
+ ossFile.setStatus(FileStatusEnum.STATUS_UPLOAD_FAIL.getCode());
+ ossFile.setStorageUnit(fileUploadConfig.getStorageUnit());
+ ossFile.setStorageSize(fileUploadConfig.getStorageSize());
+ ossFile.setFileFormat(fileConform);
+ // 上传文件
+ String fileUrl = fileManager.uploadByStream(
+ fileUploadConfig.getBucketName(), tgtFileKey, dto.getFileContent());
+
+ // 保存失败
+ if (Utility.isBlank(fileUrl)) {
+ fileDao.save(ossFile);
+ throw new BizException(CodeEnum.FILE_UPLOAD_FAILED);
+ }
+
+ ossFile.setFileUuid(uuid);
+ ossFile.setFileUrl(fileUrl);
+ ossFile.setUrlMd5(Utility.getMd5(fileUrl));
+ ossFile.setStatus(FileStatusEnum.STATUS_UPLOAD_SUCCESS.getCode());
+ ossFile.setFileName(dto.getFileName());
+ ossFile.setFileMd5(Utility.getMd5(dto.getFileContent()));
+ fileDao.save(ossFile);
+ return ossFile;
+ }
+
+ private ServerFileUploadResponse setResponse(File ossFile){
+ ServerFileUploadResponse response = new ServerFileUploadResponse();
+ response.setUrl(ossFile.getFileUrl());
+ response.setUrlMd5(ossFile.getUrlMd5());
+ response.setFileKey(ossFile.getFileUuid());
+ return response;
+ }
+
+}
diff --git a/oss-test/src/test/java/cn/axzo/oss/test/FileServiceTest.java b/oss-test/src/test/java/cn/axzo/oss/test/FileServiceTest.java
new file mode 100644
index 0000000..1b52bdb
--- /dev/null
+++ b/oss-test/src/test/java/cn/axzo/oss/test/FileServiceTest.java
@@ -0,0 +1,61 @@
+package cn.axzo.oss.test;
+
+import cn.axzo.oss.manager.api.dto.request.ServerFileDeleteDto;
+import cn.axzo.oss.manager.api.dto.request.ServerFileUploadDto;
+import cn.axzo.oss.service.api.FileService;
+import cn.axzo.oss.test.base.SpringTestBase;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @program: oss
+ * @description: 文件服务测试
+ * @author: mr.jie
+ * @date: 2021-07-29 18:42
+ **/
+public class FileServiceTest extends SpringTestBase {
+
+ @Autowired
+ private FileService fileService;
+
+ @Test
+ public void deleteTest() {
+ ServerFileDeleteDto dto = new ServerFileDeleteDto();
+ dto.setUrl("https://axzo-public.oss-cn-chengdu.aliyuncs.com/109/108046507ad94bf084aa86c07d743799.jpg");
+ dto.setOperator("zhangsan");
+ fileService.delete(dto);
+ }
+
+
+ @Test
+ public void upload() {
+ ServerFileUploadDto dto = new ServerFileUploadDto();
+ dto.setAppCode("test");
+ dto.setBizScene("1");
+ dto.setFileName("一个新的文件.xlsx");
+
+ File file = new File("/Users/admin/Downloads/表扬人员名称.xlsx");
+
+ FileInputStream fileInputStream = null;
+
+ byte[] bytes = new byte[(int) file.length()];
+ try {
+ fileInputStream = new FileInputStream(file);
+ fileInputStream.read(bytes);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+// System.out.println(Arrays.toString(bytes));
+ dto.setFileContent(bytes);
+//
+// fileService.upload(dto);
+ }
+
+
+}
diff --git a/oss-test/src/test/java/cn/axzo/oss/test/base/SpringTestBase.java b/oss-test/src/test/java/cn/axzo/oss/test/base/SpringTestBase.java
new file mode 100644
index 0000000..60787f6
--- /dev/null
+++ b/oss-test/src/test/java/cn/axzo/oss/test/base/SpringTestBase.java
@@ -0,0 +1,18 @@
+package cn.axzo.oss.test.base;
+
+import cn.axzo.oss.client.Bootstrap;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @program: oss
+ * @description: 测试基础
+ * @author: mr.jie
+ * @date: 2021-07-29 18:43
+ **/
+@SpringBootTest(classes = Bootstrap.class)
+@RunWith(SpringJUnit4ClassRunner.class)
+public class SpringTestBase {
+
+}
diff --git a/pom.xml b/pom.xml
index 39ffefb..6b5551c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,6 +37,8 @@
2.0
2.2.1.RELEASE
Hoxton.SR6
+ 1.10
+ 3.10.2
@@ -157,6 +159,16 @@
xxl-job-core
${xxl.job.version}
+
+ commons-codec
+ commons-codec
+ ${commons-codec.version}
+
+
+ com.aliyun.oss
+ aliyun-sdk-oss
+ ${aliyun-oss.version}
+