完成 对象存储多种方式的支持

This commit is contained in:
terrfly 2021-07-12 17:51:53 +08:00
parent ee361e2b80
commit b4f9a22618
26 changed files with 496 additions and 227 deletions

View File

@ -21,7 +21,7 @@ spring:
number_format: '#' #数字格式进行原样显示,不加格式化字符例如 100,00
datasource:
# yml填写url连接串 无需将&符号进行转义
url: jdbc:mysql://127.0.0.1:3306/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false
url: jdbc:mysql://127.0.0.1:3307/jeepaydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
username: root
password:
druid:
@ -90,8 +90,20 @@ isys:
#是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时应开启此配置或在nginx统一配置允许跨域]
allow-cors: true
# 文件系统配置项系统内oss 并非云oss
oss-file:
root-path: /home/jeepay/upload #存储根路径 ( 无需以‘/’结尾 )
public-path: ${isys.oss-file.root-path}/public #公共读取块 ( 一般配合root-path参数进行设置需以/ 开头, 无需以‘/’结尾 )
private-path: ${isys.oss-file.root-path}/private #私有化本地访问不允许url方式公共读取 ( 一般配合root-path参数进行设置需以/ 开头, 无需以‘/’结尾 )
oss:
file-root-path: /home/jeepay/upload #存储根路径 ( 无需以‘/’结尾 )
file-public-path: ${isys.oss.file-root-path}/public #公共读取块 ( 一般配合root-path参数进行设置需以/ 开头, 无需以‘/’结尾 )
file-private-path: ${isys.oss.file-root-path}/private #私有化本地访问不允许url方式公共读取 ( 一般配合root-path参数进行设置需以/ 开头, 无需以‘/’结尾 )
# [local]: 本地存储所有的文件将存在放本地可通过nfs, rsync工具实现多机共享
# [aliyun-oss]: 将文件统一上传到阿里云oss服务器;
service-type: local
# 阿里云OSS服务配置信息
aliyun-oss:
endpoint: oss-cn-beijing.aliyuncs.com #endpoint 如: oss-cn-beijing.aliyuncs.com
public-bucket-name: bucket1 #公共读 桶名称
private-bucket-name: bucket2 #私有 桶名称
access-key-id: KEY_KEY_KEY #AccessKeyId
access-key-secret: SECRET_SECRET_SECRET #AccessKeySecret

View File

@ -0,0 +1,10 @@
package com.jeequan.jeepay.core.service;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
public interface ISysConfigService {
/** 获取应用的配置参数 **/
DBApplicationConfig getDBApplicationConfig();
}

View File

@ -25,6 +25,13 @@
<version>${isys.version}</version>
</dependency>
<!-- 依赖[ oss ]包 -->
<dependency>
<groupId>com.jeequan</groupId>
<artifactId>jeepay-oss</artifactId>
<version>${isys.version}</version>
</dependency>
<!-- 依赖 sping-boot-web -->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@ -17,7 +17,6 @@ package com.jeequan.jeepay.mgr.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
/**
@ -38,23 +37,6 @@ public class SystemYmlConfig {
/** 生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。 **/
private String jwtSecret;
@NestedConfigurationProperty //指定该属性为嵌套值, 否则默认为简单值导致对象为空外部类不存在该问题 内部static需明确指定
private OssFile ossFile;
/** 系统oss配置信息 **/
@Data
public static class OssFile{
/** 存储根路径 **/
private String rootPath;
/** 公共读取块 **/
private String publicPath;
/** 私有读取块 **/
private String privatePath;
}
}

View File

@ -16,6 +16,8 @@
package com.jeequan.jeepay.mgr.ctrl.common;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.oss.config.OssYmlConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@ -38,6 +40,8 @@ import java.io.InputStream;
@Controller
public class StaticController extends CommonCtrl {
@Autowired private OssYmlConfig ossYmlConfig;
/** 图片预览 **/
@GetMapping("/api/anon/localOssFiles/**/*.*")
public ResponseEntity<?> imgView() {
@ -45,7 +49,7 @@ public class StaticController extends CommonCtrl {
try {
//查找图片文件
File imgFile = new File(mainConfig.getOssFile().getPublicPath() + File.separator + request.getRequestURI().substring(24));
File imgFile = new File(ossYmlConfig.getOss().getFilePublicPath() + File.separator + request.getRequestURI().substring(24));
if(!imgFile.isFile() || !imgFile.exists()) return new ResponseEntity<>(HttpStatus.NOT_FOUND);
//输出文件流图片格式

View File

@ -25,6 +25,13 @@
<version>${isys.version}</version>
</dependency>
<!-- 依赖[ oss ]包 -->
<dependency>
<groupId>com.jeequan</groupId>
<artifactId>jeepay-oss</artifactId>
<version>${isys.version}</version>
</dependency>
<!-- 依赖 sping-boot-web -->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@ -17,7 +17,6 @@ package com.jeequan.jeepay.mch.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
/**
@ -38,21 +37,4 @@ public class SystemYmlConfig {
/** 生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。 **/
private String jwtSecret;
@NestedConfigurationProperty //指定该属性为嵌套值, 否则默认为简单值导致对象为空外部类不存在该问题 内部static需明确指定
private OssFile ossFile;
/** 系统oss配置信息 **/
@Data
public static class OssFile{
/** 存储根路径 **/
private String rootPath;
/** 公共读取块 **/
private String publicPath;
/** 私有读取块 **/
private String privatePath;
}
}
}

View File

@ -1,111 +0,0 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.ctrl.common;
import cn.hutool.core.lang.UUID;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.OssFileConfig;
import com.jeequan.jeepay.core.utils.FileKit;
import com.jeequan.jeepay.mch.config.SystemYmlConfig;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.SysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
/*
* 统一文件上传接口ossFile
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:07
*/
@RestController
@RequestMapping("/api/ossFiles")
public class OssFileController extends CommonCtrl {
@Autowired private SystemYmlConfig systemYmlConfig;
@Autowired private SysConfigService sysConfigService;
/** 上传文件 (单文件上传) */
@PostMapping("/{bizType}")
public ApiRes singleFileUpload(@RequestParam("file") MultipartFile file, @PathVariable("bizType") String bizType) {
if( file == null ) return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "选择文件不存在");
try {
OssFileConfig ossFileConfig = OssFileConfig.getOssFileConfigByBizType(bizType);
//1. 判断bizType 是否可用
if(ossFileConfig == null){
throw new BizException("类型有误");
}
// 2. 判断文件是否支持
String fileSuffix = FileKit.getFileSuffix(file.getOriginalFilename(), false);
if( !ossFileConfig.isAllowFileSuffix(fileSuffix) ){
throw new BizException("上传文件格式不支持!");
}
// 3. 判断文件大小是否超限
if( !ossFileConfig.isMaxSizeLimit(file.getSize()) ){
throw new BizException("上传大小请限制在["+ossFileConfig.getMaxSize() / 1024 / 1024 +"M]以内!");
}
boolean isAllowPublicRead = ossFileConfig.isAllowPublicRead(); //是否允许公共读 true公共读 false私有文件
//公共读 & 是否上传到oss
boolean isYunOss = false; //TODO 暂时不支持云oss方式
if(isAllowPublicRead && isYunOss){
return null;
}
//以下为文件上传到本地
// 新文件地址
String newFileName = UUID.fastUUID() + "." + fileSuffix;
// 保存的文件夹名称
String saveFilePath = isAllowPublicRead ? systemYmlConfig.getOssFile().getPublicPath() : systemYmlConfig.getOssFile().getPrivatePath();
saveFilePath = saveFilePath + File.separator + bizType + File.separator + newFileName;
//保存文件
saveFile(file, saveFilePath);
//返回响应结果
String resultUrl = bizType + "/" + newFileName;
if(isAllowPublicRead){ //允许公共读取
resultUrl = sysConfigService.getDBApplicationConfig().getOssPublicSiteUrl() + "/" + resultUrl;
}
return ApiRes.ok(resultUrl);
} catch (BizException biz) {
throw biz;
} catch (Exception e) {
logger.error("upload error, fileName = {}", file == null ? null :file.getOriginalFilename(), e);
throw new BizException(ApiCodeEnum.SYSTEM_ERROR);
}
}
}

77
jeepay-oss/pom.xml Normal file
View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <!-- POM模型版本 -->
<groupId>com.jeequan</groupId> <!-- 组织名, 类似于包名 -->
<artifactId>jeepay-oss</artifactId> <!-- 项目名称 -->
<packaging>jar</packaging> <!-- 项目的最终打包类型/发布形式, 可选[jar, war, pom, maven-plugin]等 -->
<version>${isys.version}</version> <!-- 项目当前版本号 -->
<description>Jeepay计全支付系统 [jeepay-oss]</description> <!-- 项目描述 -->
<url>https://www.jeequan.com</url>
<parent>
<groupId>com.jeequan</groupId>
<artifactId>jeepay</artifactId>
<version>Final</version>
</parent>
<!-- 项目依赖声明 -->
<dependencies>
<dependency>
<groupId>com.jeequan</groupId>
<artifactId>jeepay-core</artifactId>
<version>${isys.version}</version>
</dependency>
<!-- 添加 spring-webmvc 基础依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<scope>provided</scope> <!-- 仅编译依赖该jar 运行时存在 -->
</dependency>
<!-- slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<!-- spring-boot 相关注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<scope>provided</scope> <!-- 仅编译依赖该jar 运行时存在 -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<scope>provided</scope> <!-- 仅编译依赖该jar 运行时存在 -->
</dependency>
<!-- 阿里云oss组件 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<scope>provided</scope> <!-- 当对象存储使用aliyunOSS时需要改为compile 否则使用provided仅用于编译代码 -->
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes><include>**/*.xml</include></includes><!-- maven可以将mapper.xml进行打包处理否则仅对java文件处理 -->
</resource>
</resources>
</build>
</project>

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.oss.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 系统Yml配置参数定义Bean
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@Data
@Component
@ConfigurationProperties(prefix="isys.oss.aliyun-oss")
public class AliyunOssYmlConfig {
private String endpoint;
private String publicBucketName;
private String privateBucketName;
private String accessKeyId;
private String accessKeySecret;
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.oss.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
/**
* 系统Yml配置参数定义Bean
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@Data
@Component
@ConfigurationProperties(prefix="isys")
public class OssYmlConfig {
@NestedConfigurationProperty //指定该属性为嵌套值, 否则默认为简单值导致对象为空外部类不存在该问题 内部static需明确指定
private Oss oss;
/** 系统oss配置信息 **/
@Data
public static class Oss{
/** 存储根路径 **/
private String fileRootPath;
/** 公共读取块 **/
private String filePublicPath;
/** 私有读取块 **/
private String filePrivatePath;
/** oss类型 **/
private String serviceType;
}
}

View File

@ -0,0 +1,15 @@
package com.jeequan.jeepay.oss.constant;
/*
* oss 存储位置
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/7/12 10:48
*/
public enum OssSavePlaceEnum {
PUBLIC, //公共读取
PRIVATE; //私有存储
}

View File

@ -0,0 +1,25 @@
package com.jeequan.jeepay.oss.constant;
import lombok.Data;
import lombok.Getter;
/*
* oss 服务枚举值
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/7/12 10:48
*/
@Getter
public enum OssServiceTypeEnum {
LOCAL("local"), //本地存储
ALIYUN_OSS("aliyun-oss"); //阿里云oss
/** 名称 **/
private String serviceName;
OssServiceTypeEnum(String serviceName){
this.serviceName = serviceName;
}
}

View File

@ -13,23 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mgr.ctrl.common;
package com.jeequan.jeepay.oss.ctrl;
import cn.hutool.core.lang.UUID;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.ctrls.AbstractCtrl;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.OssFileConfig;
import com.jeequan.jeepay.core.utils.FileKit;
import com.jeequan.jeepay.mgr.config.SystemYmlConfig;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.service.impl.SysConfigService;
import com.jeequan.jeepay.oss.model.OssFileConfig;
import com.jeequan.jeepay.oss.service.IOssService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
/*
* 统一文件上传接口ossFile
*
@ -39,10 +36,9 @@ import java.io.File;
*/
@RestController
@RequestMapping("/api/ossFiles")
public class OssFileController extends CommonCtrl {
public class OssFileController extends AbstractCtrl {
@Autowired private SystemYmlConfig systemYmlConfig;
@Autowired private SysConfigService sysConfigService;
@Autowired private IOssService ossService;
/** 上传文件 (单文件上传) */
@PostMapping("/{bizType}")
@ -51,7 +47,6 @@ public class OssFileController extends CommonCtrl {
if( file == null ) return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "选择文件不存在");
try {
OssFileConfig ossFileConfig = OssFileConfig.getOssFileConfigByBizType(bizType);
//1. 判断bizType 是否可用
@ -70,35 +65,10 @@ public class OssFileController extends CommonCtrl {
throw new BizException("上传大小请限制在["+ossFileConfig.getMaxSize() / 1024 / 1024 +"M]以内!");
}
boolean isAllowPublicRead = ossFileConfig.isAllowPublicRead(); //是否允许公共读 true公共读 false私有文件
//公共读 & 是否上传到oss
boolean isYunOss = false; //TODO 暂时不支持云oss方式
if(isAllowPublicRead && isYunOss){
return null;
}
//以下为文件上传到本地
// 新文件地址
String newFileName = UUID.fastUUID() + "." + fileSuffix;
// 保存的文件夹名称
String saveFilePath = isAllowPublicRead ? systemYmlConfig.getOssFile().getPublicPath() : systemYmlConfig.getOssFile().getPrivatePath();
saveFilePath = saveFilePath + File.separator + bizType + File.separator + newFileName;
//保存文件
saveFile(file, saveFilePath);
//返回响应结果
String resultUrl = bizType + "/" + newFileName;
if(isAllowPublicRead){ //允许公共读取
resultUrl = sysConfigService.getDBApplicationConfig().getOssPublicSiteUrl() + "/" + resultUrl;
}
return ApiRes.ok(resultUrl);
// 新文件地址 (xxx/xxx.jpg 格式)
String saveDirAndFileName = bizType + "/" + UUID.fastUUID() + "." + fileSuffix;
String url = ossService.upload2PreviewUrl(ossFileConfig.getOssSavePlaceEnum(), file, saveDirAndFileName);
return ApiRes.ok(url);
} catch (BizException biz) {
throw biz;
@ -108,4 +78,4 @@ public class OssFileController extends CommonCtrl {
}
}
}
}

View File

@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.core.model;
package com.jeequan.jeepay.oss.model;
import com.jeequan.jeepay.oss.constant.OssSavePlaceEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
@ -53,13 +54,13 @@ public class OssFileConfig {
private static final Map<String, OssFileConfig> ALL_BIZ_TYPE_MAP = new HashMap<>();
static{
ALL_BIZ_TYPE_MAP.put(BIZ_TYPE.AVATAR, new OssFileConfig(true, IMG_SUFFIX, DEFAULT_MAX_SIZE) );
ALL_BIZ_TYPE_MAP.put(BIZ_TYPE.IF_BG, new OssFileConfig(true, IMG_SUFFIX, DEFAULT_MAX_SIZE) );
ALL_BIZ_TYPE_MAP.put(BIZ_TYPE.CERT, new OssFileConfig(false, new HashSet<>(Arrays.asList(ALL_SUFFIX_FLAG)), DEFAULT_MAX_SIZE) );
ALL_BIZ_TYPE_MAP.put(BIZ_TYPE.AVATAR, new OssFileConfig(OssSavePlaceEnum.PUBLIC, IMG_SUFFIX, DEFAULT_MAX_SIZE) );
ALL_BIZ_TYPE_MAP.put(BIZ_TYPE.IF_BG, new OssFileConfig(OssSavePlaceEnum.PUBLIC, IMG_SUFFIX, DEFAULT_MAX_SIZE) );
ALL_BIZ_TYPE_MAP.put(BIZ_TYPE.CERT, new OssFileConfig(OssSavePlaceEnum.PRIVATE, new HashSet<>(Arrays.asList(ALL_SUFFIX_FLAG)), DEFAULT_MAX_SIZE) );
}
/** 是否允许公共读 **/
private boolean allowPublicRead = false;
/** 存储位置 **/
private OssSavePlaceEnum ossSavePlaceEnum;
/** 允许的文件后缀, 默认全部类型 **/
private Set<String> allowFileSuffix = new HashSet<>(Arrays.asList(ALL_SUFFIX_FLAG));

View File

@ -0,0 +1,62 @@
package com.jeequan.jeepay.oss.service;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.GetObjectRequest;
import com.jeequan.jeepay.oss.config.AliyunOssYmlConfig;
import com.jeequan.jeepay.oss.constant.OssSavePlaceEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
@Service
@Slf4j
@ConditionalOnProperty(name = "isys.oss.service-type", havingValue = "aliyun-oss")
public class AliyunOssService implements IOssService{
@Autowired private AliyunOssYmlConfig aliyunOssYmlConfig;
@Override
public String upload2PreviewUrl(OssSavePlaceEnum ossSavePlaceEnum, MultipartFile multipartFile, String saveDirAndFileName) {
try {
// 创建OSSClient实例
OSS client = new OSSClientBuilder().build(aliyunOssYmlConfig.getEndpoint(), aliyunOssYmlConfig.getAccessKeyId(), aliyunOssYmlConfig.getAccessKeySecret());
client.putObject(aliyunOssYmlConfig.getPublicBucketName(), saveDirAndFileName, multipartFile.getInputStream());
if(ossSavePlaceEnum == OssSavePlaceEnum.PUBLIC){
// 文档https://www.alibabacloud.com/help/zh/doc-detail/39607.htm example: https://BucketName.Endpoint/ObjectName
return "https://" + aliyunOssYmlConfig.getPublicBucketName() + "." + aliyunOssYmlConfig.getEndpoint() + "/" + saveDirAndFileName;
}
return saveDirAndFileName;
} catch (Exception e) {
log.error("error", e);
return null;
}
}
@Override
public boolean downloadFile(OssSavePlaceEnum ossSavePlaceEnum, String source, String target) {
try {
// 创建OSSClient实例
OSS client = new OSSClientBuilder().build(aliyunOssYmlConfig.getEndpoint(), aliyunOssYmlConfig.getAccessKeyId(), aliyunOssYmlConfig.getAccessKeySecret());
String bucket = ossSavePlaceEnum == OssSavePlaceEnum.PRIVATE ? aliyunOssYmlConfig.getPrivateBucketName() : aliyunOssYmlConfig.getPublicBucketName();
client.getObject(new GetObjectRequest(bucket, source), new File(target));
return true;
} catch (Exception e) {
log.error("error", e);
return false;
}
}
}

View File

@ -0,0 +1,17 @@
package com.jeequan.jeepay.oss.service;
import com.jeequan.jeepay.oss.constant.OssSavePlaceEnum;
import org.springframework.web.multipart.MultipartFile;
public interface IOssService {
/** 上传文件 & 生成下载/预览URL **/
String upload2PreviewUrl(OssSavePlaceEnum ossSavePlaceEnum, MultipartFile multipartFile, String saveDirAndFileName);
/** 将文件下载到本地
* 返回是否 写入成功
* false: 写入失败 或者文件不存在
* **/
boolean downloadFile(OssSavePlaceEnum ossSavePlaceEnum, String source, String target);
}

View File

@ -0,0 +1,54 @@
package com.jeequan.jeepay.oss.service;
import com.jeequan.jeepay.core.service.ISysConfigService;
import com.jeequan.jeepay.oss.config.OssYmlConfig;
import com.jeequan.jeepay.oss.constant.OssSavePlaceEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
@Service
@Slf4j
@ConditionalOnProperty(name = "isys.oss.service-type", havingValue = "local")
public class LocalFileService implements IOssService{
@Autowired private ISysConfigService sysConfigService;
@Autowired private OssYmlConfig ossYmlConfig;
@Override
public String upload2PreviewUrl(OssSavePlaceEnum ossSavePlaceEnum, MultipartFile multipartFile, String saveDirAndFileName) {
try {
String savePath = ossSavePlaceEnum ==
OssSavePlaceEnum.PUBLIC ? ossYmlConfig.getOss().getFilePublicPath() : ossYmlConfig.getOss().getFilePrivatePath();
File saveFile = new File(savePath + File.separator + saveDirAndFileName);
//如果文件夹不存在则创建文件夹
File dir = saveFile.getParentFile();
if(!dir.exists()) dir.mkdirs();
multipartFile.transferTo(saveFile);
} catch (Exception e) {
log.error("", e);
}
// 私有文件 不返回预览文件地址
if(ossSavePlaceEnum == OssSavePlaceEnum.PRIVATE){
return saveDirAndFileName;
}
return sysConfigService.getDBApplicationConfig().getOssPublicSiteUrl() + "/" + saveDirAndFileName;
}
@Override
public boolean downloadFile(OssSavePlaceEnum ossSavePlaceEnum, String source, String target) {
return false;
}
}

View File

View File

View File

@ -25,6 +25,13 @@
<version>${isys.version}</version>
</dependency>
<!-- 依赖[ oss ]包 -->
<dependency>
<groupId>com.jeequan</groupId>
<artifactId>jeepay-oss</artifactId>
<version>${isys.version}</version>
</dependency>
<!-- 依赖 sping-boot-web -->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@ -17,7 +17,6 @@ package com.jeequan.jeepay.pay.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
/**
@ -35,22 +34,4 @@ public class SystemYmlConfig {
/** 是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时应开启此配置或在nginx统一配置允许跨域] **/
private Boolean allowCors;
@NestedConfigurationProperty //指定该属性为嵌套值, 否则默认为简单值导致对象为空外部类不存在该问题 内部static需明确指定
private OssFile ossFile;
/** 系统oss配置信息 **/
@Data
public static class OssFile{
/** 存储根路径 **/
private String rootPath;
/** 公共读取块 **/
private String publicPath;
/** 私有读取块 **/
private String privatePath;
}
}
}

View File

@ -42,6 +42,7 @@ import com.jeequan.jeepay.service.impl.IsvInfoService;
import com.jeequan.jeepay.service.impl.MchAppService;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
@ -59,6 +60,7 @@ import java.util.concurrent.ConcurrentHashMap;
* @site https://www.jeepay.vip
* @date 2021/6/8 17:41
*/
@Slf4j
@Service
public class ConfigContextService {
@ -354,7 +356,8 @@ public class ConfigContextService {
try {
alipayClient = new DefaultAlipayClient(certAlipayRequest);
} catch (AlipayApiException e) {
e.printStackTrace();
log.error("error" ,e);
alipayClient = null;
}
}else{
alipayClient = new DefaultAlipayClient(sandbox == CS.YES ? AlipayConfig.SANDBOX_SERVER_URL : AlipayConfig.PROD_SERVER_URL

View File

@ -1,10 +1,17 @@
package com.jeequan.jeepay.pay.util;
import cn.hutool.core.io.FileUtil;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.oss.config.OssYmlConfig;
import com.jeequan.jeepay.oss.constant.OssSavePlaceEnum;
import com.jeequan.jeepay.oss.constant.OssServiceTypeEnum;
import com.jeequan.jeepay.oss.service.IOssService;
import com.jeequan.jeepay.pay.config.SystemYmlConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
/*
* 支付平台 获取系统文件工具类
@ -16,13 +23,59 @@ import java.io.File;
@Component
public class ChannelCertConfigKitBean {
@Autowired private SystemYmlConfig systemYmlConfig;
@Autowired private OssYmlConfig ossYmlConfig;
@Autowired private IOssService ossService;
public String getCertFilePath(String certFilePath){
return systemYmlConfig.getOssFile().getPrivatePath() + File.separator + certFilePath;
return getCertFile(certFilePath).getAbsolutePath();
}
public File getCertFile(String certFilePath){
return new File(getCertFilePath(certFilePath));
File certFile = new File(ossYmlConfig.getOss().getFilePrivatePath() + File.separator + certFilePath);
if(certFile.exists()){ // 本地存在直接返回
return certFile;
}
// 以下为 文件不存在的处理方式
// 是否本地存储
boolean isLocalSave = OssServiceTypeEnum.LOCAL.equals(ossYmlConfig.getOss().getServiceType());
// 本地存储 & 文件不存在
if(isLocalSave){
return certFile;
}
// 已经向oss请求并且返回了空文件时
if(new File(certFile.getAbsolutePath() + ".notexists").exists()){
return certFile;
}
// 请求下载并返回 新File
return downloadFile(certFilePath, certFile);
}
/** 下载文件 **/
private synchronized File downloadFile(String dbCertFilePath, File certFile){
//请求文件并写入
boolean isSuccess = ossService.downloadFile(OssSavePlaceEnum.PRIVATE, dbCertFilePath, certFile.getAbsolutePath());
// 下载成功 返回新的File对象
if(isSuccess) {
return new File(certFile.getAbsolutePath());
}
// 下载失败 写入.notexists文件 避免那下次再次下载影响效率
try {
new File(certFile.getAbsolutePath() + ".notexists").createNewFile();
} catch (IOException e) {
}
return certFile;
}
}

View File

@ -19,6 +19,7 @@ import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.core.entity.SysConfig;
import com.jeequan.jeepay.core.model.DBApplicationConfig;
import com.jeequan.jeepay.core.service.ISysConfigService;
import com.jeequan.jeepay.service.mapper.SysConfigMapper;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
@ -36,7 +37,7 @@ import java.util.Set;
* @since 2020-07-29
*/
@Service
public class SysConfigService extends ServiceImpl<SysConfigMapper, SysConfig> {
public class SysConfigService extends ServiceImpl<SysConfigMapper, SysConfig> implements ISysConfigService {
@Autowired
private SysConfigService sysConfigService;

10
pom.xml
View File

@ -25,9 +25,12 @@
<module>jeepay-core</module> <!-- 基础函数, 包含工具类等 -->
<module>jeepay-service</module> <!-- db service等 -->
<module>jeepay-oss</module> <!-- oss服务支撑 -->
<module>jeepay-manager</module> <!-- 运营平台管理端 -->
<module>jeepay-merchant</module> <!-- 商户平台管理端 -->
<module>jeepay-payment</module> <!-- 支付统一网关 -->
</modules>
<!-- 配置属性声明, 支持自定义参数 -->
@ -120,6 +123,13 @@
<version>4.13.50.ALL</version>
</dependency>
<!-- 阿里云oss组件 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.13.0</version>
</dependency>
</dependencies>
</dependencyManagement>