提交 5fe72576 编写于 作者: zlt2000's avatar zlt2000

新增oss的starter同时支持云oss、minio与fastdfs

上级 b0768b85
......@@ -350,6 +350,11 @@
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>com.zlt</groupId>
<artifactId>zlt-oss-spring-boot-starter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
......
......@@ -30,6 +30,10 @@
<groupId>com.zlt</groupId>
<artifactId>zlt-sentinel-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.zlt</groupId>
<artifactId>zlt-oss-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
......@@ -66,21 +70,21 @@
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<!-- 阿里云oss -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<!-- 七牛oss -->
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
</dependency>
<!-- fastDFS -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
</dependency>
<!-- aws s3 -->
<!--<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
</dependency>-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
</dependencies>
<build>
......
package com.central;
import com.central.common.ribbon.annotation.EnableFeignInterceptor;
import com.central.file.properties.FileServerProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
......@@ -13,7 +11,6 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
* @author 作者 owen E-mail: 624191343@qq.com
*/
@EnableDiscoveryClient
@EnableConfigurationProperties(FileServerProperties.class)
@EnableFeignClients
@EnableFeignInterceptor
@SpringBootApplication
......
package com.central.file.config;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.central.file.model.FileInfo;
import com.central.file.properties.FileServerProperties;
import com.central.file.service.impl.AbstractIFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.aliyun.oss.OSSClient;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
/**
* 阿里云配置
*
* @author 作者 owen E-mail: 624191343@qq.com
*/
@Configuration
@ConditionalOnProperty(name = "zlt.file-server.type", havingValue = "aliyun")
public class AliyunOSSAutoConfigure {
@Autowired
private FileServerProperties fileProperties;
/**
* 阿里云文件存储client
* 只有配置了aliyun.oss.access-key才可以使用
*/
@Bean
public OSSClient ossClient() {
OSSClient ossClient = new OSSClient(fileProperties.getOss().getEndpoint()
, new DefaultCredentialProvider(fileProperties.getOss().getAccessKey(), fileProperties.getOss().getAccessKeySecret())
, null);
return ossClient;
}
@Service
public class AliyunOssServiceImpl extends AbstractIFileService {
@Autowired
private OSSClient ossClient;
@Override
protected String fileType() {
return fileProperties.getType();
}
@Override
protected void uploadFile(MultipartFile file, FileInfo fileInfo) throws Exception {
ossClient.putObject(fileProperties.getOss().getBucketName(), fileInfo.getName(), file.getInputStream());
fileInfo.setUrl(fileProperties.getOss().getDomain() + "/" + fileInfo.getName());
}
@Override
protected boolean deleteFile(FileInfo fileInfo) {
ossClient.deleteObject(fileProperties.getOss().getBucketName(), fileInfo.getName());
return true;
}
}
}
package com.central.file.config;
import cn.hutool.core.util.StrUtil;
import com.central.file.model.FileInfo;
import com.central.file.properties.FileServerProperties;
import com.central.file.service.impl.AbstractIFileService;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
/**
* FastDFS配置
*
* @author zlt
*/
@Configuration
@ConditionalOnProperty(name = "zlt.file-server.type", havingValue = "fastdfs")
public class FastdfsAutoConfigure {
@Autowired
private FileServerProperties fileProperties;
@Service
public class FastdfsServiceImpl extends AbstractIFileService {
@Autowired
private FastFileStorageClient storageClient;
@Override
protected String fileType() {
return fileProperties.getType();
}
@Override
protected void uploadFile(MultipartFile file, FileInfo fileInfo) throws Exception {
StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()), null);
fileInfo.setUrl("http://" + fileProperties.getFdfs().getWebUrl() + "/" + storePath.getFullPath());
fileInfo.setPath(storePath.getFullPath());
}
@Override
protected boolean deleteFile(FileInfo fileInfo) {
if (fileInfo != null && StrUtil.isNotEmpty(fileInfo.getPath())) {
StorePath storePath = StorePath.parseFromUrl(fileInfo.getPath());
storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
}
return true;
}
}
}
package com.central.file.config;
import com.central.file.model.FileInfo;
import com.central.file.properties.FileServerProperties;
import com.central.file.service.impl.AbstractIFileService;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.qiniu.common.Zone;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
/**
* 七牛云配置
*
* @author 作者 owen E-mail: 624191343@qq.com
*/
@Configuration
@ConditionalOnProperty(name = "zlt.file-server.type", havingValue = "qiniu")
public class QiniuOSSAutoConfigure {
@Autowired
private FileServerProperties fileProperties;
/**
* 华东机房
*/
@Bean
public com.qiniu.storage.Configuration qiniuConfig() {
return new com.qiniu.storage.Configuration(Zone.zone2());
}
/**
* 构建一个七牛上传工具实例
*/
@Bean
public UploadManager uploadManager() {
return new UploadManager(qiniuConfig());
}
/**
* 认证信息实例
*
* @return
*/
@Bean
public Auth auth() {
return Auth.create(fileProperties.getOss().getAccessKey(), fileProperties.getOss().getAccessKeySecret());
}
/**
* 构建七牛空间管理实例
*/
@Bean
public BucketManager bucketManager() {
return new BucketManager(auth(), qiniuConfig());
}
@Service
public class QiniuOssServiceImpl extends AbstractIFileService {
@Autowired
private UploadManager uploadManager;
@Autowired
private BucketManager bucketManager;
@Autowired
private Auth auth;
@Override
protected String fileType() {
return fileProperties.getType();
}
@Override
protected void uploadFile(MultipartFile file, FileInfo fileInfo) throws Exception {
// 调用put方法上传
uploadManager.put(file.getBytes(), fileInfo.getName(), auth.uploadToken(fileProperties.getOss().getBucketName()));
fileInfo.setUrl(fileProperties.getOss().getEndpoint() + "/" + fileInfo.getName());
fileInfo.setPath(fileProperties.getOss().getEndpoint() + "/" + fileInfo.getName());
}
@Override
protected boolean deleteFile(FileInfo fileInfo) {
try {
Response response = bucketManager.delete(fileProperties.getOss().getBucketName(), fileInfo.getPath());
int retry = 0;
while (response.needRetry() && retry++ < 3) {
response = bucketManager.delete(fileProperties.getOss().getBucketName(), fileInfo.getPath());
}
} catch (QiniuException e) {
return false;
}
return true;
}
}
}
package com.central.file.service;
import java.io.OutputStream;
import java.util.Map;
import com.baomidou.mybatisplus.extension.service.IService;
......@@ -19,4 +20,6 @@ public interface IFileService extends IService<FileInfo> {
PageResult<FileInfo> findList(Map<String, Object> params);
void delete(String id);
void out(String id, OutputStream os);
}
......@@ -5,6 +5,7 @@ import java.util.Map;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.central.oss.model.ObjectInfo;
import org.apache.commons.collections4.MapUtils;
import org.springframework.web.multipart.MultipartFile;
......@@ -27,12 +28,14 @@ public abstract class AbstractIFileService extends ServiceImpl<FileMapper, FileI
private static final String FILE_SPLIT = ".";
@Override
public FileInfo upload(MultipartFile file) throws Exception {
public FileInfo upload(MultipartFile file) {
FileInfo fileInfo = FileUtil.getFileInfo(file);
if (!fileInfo.getName().contains(FILE_SPLIT)) {
throw new IllegalArgumentException("缺少后缀名");
}
uploadFile(file, fileInfo);
ObjectInfo objectInfo = uploadFile(file);
fileInfo.setPath(objectInfo.getObjectPath());
fileInfo.setUrl(objectInfo.getObjectUrl());
// 设置文件来源
fileInfo.setSource(fileType());
// 将文件信息保存到数据库
......@@ -52,9 +55,8 @@ public abstract class AbstractIFileService extends ServiceImpl<FileMapper, FileI
* 上传文件
*
* @param file
* @param fileInfo
*/
protected abstract void uploadFile(MultipartFile file, FileInfo fileInfo) throws Exception;
protected abstract ObjectInfo uploadFile(MultipartFile file);
/**
* 删除文件
......@@ -65,17 +67,16 @@ public abstract class AbstractIFileService extends ServiceImpl<FileMapper, FileI
FileInfo fileInfo = baseMapper.selectById(id);
if (fileInfo != null) {
baseMapper.deleteById(fileInfo.getId());
this.deleteFile(fileInfo);
this.deleteFile(fileInfo.getPath());
}
}
/**
* 删除文件资源
*
* @param fileInfo
* @return
* @param objectPath 文件路径
*/
protected abstract boolean deleteFile(FileInfo fileInfo);
protected abstract void deleteFile(String objectPath);
@Override
public PageResult<FileInfo> findList(Map<String, Object> params) {
......
package com.central.file.service.impl;
import com.central.oss.model.ObjectInfo;
import com.central.oss.properties.FileServerProperties;
import com.central.oss.template.FdfsTemplate;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.OutputStream;
/**
* @author zlt
* @date 2021/2/13
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Service
@ConditionalOnProperty(prefix = com.central.oss.properties.FileServerProperties.PREFIX, name = "type", havingValue = FileServerProperties.TYPE_FDFS)
public class FastdfsService extends AbstractIFileService {
@Resource
private FdfsTemplate fdfsTemplate;
@Override
protected String fileType() {
return FileServerProperties.TYPE_FDFS;
}
@Override
protected ObjectInfo uploadFile(MultipartFile file) {
return fdfsTemplate.upload(file);
}
@Override
protected void deleteFile(String objectPath) {
fdfsTemplate.delete(objectPath);
}
@Override
public void out(String id, OutputStream os) {
}
}
package com.central.file.service.impl;
import cn.hutool.core.util.StrUtil;
import com.central.file.model.FileInfo;
import com.central.oss.model.ObjectInfo;
import com.central.oss.properties.FileServerProperties;
import com.central.oss.template.S3Template;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.OutputStream;
/**
* @author zlt
* @date 2021/2/13
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Service
@ConditionalOnProperty(prefix = com.central.oss.properties.FileServerProperties.PREFIX, name = "type", havingValue = FileServerProperties.TYPE_S3)
public class S3Service extends AbstractIFileService {
private static final String PATH_SPLIT = "/";
@Resource
private S3Template s3Template;
@Override
protected String fileType() {
return FileServerProperties.TYPE_S3;
}
@Override
protected ObjectInfo uploadFile(MultipartFile file) {
return s3Template.upload(file);
}
@Override
protected void deleteFile(String objectPath) {
S3Object s3Object = parsePath(objectPath);
s3Template.delete(s3Object.bucketName, s3Object.objectName);
}
@Override
public void out(String id, OutputStream os) {
FileInfo fileInfo = baseMapper.selectById(id);
if (fileInfo != null) {
S3Object s3Object = parsePath(fileInfo.getPath());
s3Template.out(s3Object.bucketName, s3Object.objectName, os);
}
}
@Setter
@Getter
private class S3Object {
private String bucketName;
private String objectName;
}
private S3Object parsePath(String path) {
S3Object s3Object = new S3Object();
if (StrUtil.isNotEmpty(path)) {
int splitIndex = path.lastIndexOf(PATH_SPLIT);
if (splitIndex != -1) {
s3Object.bucketName = path.substring(0, splitIndex);
s3Object.objectName = path.substring(splitIndex + 1);
}
}
return s3Object;
}
}
......@@ -15,16 +15,14 @@ mybatis-plus:
zlt:
file-server:
type: fastdfs
fdfs:
web-url: ${zlt.fdfs.web-url}
#oss配置
#oss:
# access-key: tpi8mObnfzZi4ggBX8Bw7zydjoTQ0WeML3RkPKsX
# accessKeySecret: HZBXmSyUTy-haYp0KbBTtsil-GoKjVS2kDKT8Yow
# endpoint: http://pkqtmn0p1.bkt.clouddn.com
# bucketName: public-oss
# domain:
type: s3
#fdfs:
# web-url: ${zlt.fdfs.web-url}
s3:
access-key: ${zlt.s3.access-key}
accessKeySecret: ${zlt.s3.accessKeySecret}
endpoint: ${zlt.s3.endpoint}
bucketName: ${zlt.s3.bucketName}
swagger:
enabled: true
title: 文件中心
......@@ -36,7 +34,7 @@ zlt:
enable: true
#fastDFS配置
fdfs:
soTimeout: 1500
connectTimeout: 600
trackerList: ${zlt.fdfs.trackerList}
\ No newline at end of file
#fdfs:
# soTimeout: 1500
# connectTimeout: 600
# trackerList: ${zlt.fdfs.trackerList}
\ No newline at end of file
......@@ -21,5 +21,6 @@
<module>zlt-sentinel-spring-boot-starter</module>
<module>zlt-common-core</module>
<module>zlt-elasticsearch-spring-boot-starter</module>
<module>zlt-oss-spring-boot-starter</module>
</modules>
</project>
\ No newline at end of file
<?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">
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>4.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>zlt-oss-spring-boot-starter</artifactId>
<description>对象存储通用组件</description>
<dependencies>
<!-- fastDFS -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<optional>true</optional>
</dependency>
<!-- aws s3 -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
package com.central.oss.config;
import com.central.oss.properties.FileServerProperties;
import com.central.oss.template.FdfsTemplate;
import com.central.oss.template.S3Template;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;
/**
* @author zlt
* @date 2021/2/13
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@EnableConfigurationProperties(FileServerProperties.class)
@Import({FdfsTemplate.class, S3Template.class})
public class OssAutoConfigure {
}
package com.central.oss.model;
import lombok.Getter;
import lombok.Setter;
/**
* @author zlt
* @date 2021/2/11
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
public class ObjectInfo {
/**
* 对象查看路径
*/
private String objectUrl;
/**
* 对象保存路径
*/
private String objectPath;
}
package com.central.file.properties;
package com.central.oss.properties;
import lombok.Getter;
import lombok.Setter;
/**
* fastdfs配置
*
* @author zlt
* @date 2021/2/11
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
......
package com.central.file.properties;
package com.central.oss.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
/**
* @author zlt
* @date 2021/2/11
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
@ConfigurationProperties(prefix = "zlt.file-server")
@RefreshScope
@ConfigurationProperties(prefix = FileServerProperties.PREFIX)
public class FileServerProperties {
public static final String PREFIX = "zlt.file-server";
public static final String TYPE_FDFS = "fastdfs";
public static final String TYPE_S3 = "s3";
/**
* 为以下3个值,指定不同的自动化配置
* qiniu:七牛oss
* aliyun:阿里云oss
* 为以下2个值,指定不同的自动化配置
* s3:aws s3协议的存储(七牛oss、阿里云oss、minio等)
* fastdfs:本地部署的fastDFS
*/
private String type;
/**
* oss配置
* aws s3配置
*/
OssProperties oss = new OssProperties();
S3Properties s3 = new S3Properties();
/**
* fastDFS配置
......
package com.central.file.properties;
package com.central.oss.properties;
import lombok.Getter;
import lombok.Setter;
/**
* aws s3协议配置
*
* @author zlt
* @date 2021/2/11
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
public class OssProperties {
public class S3Properties {
/**
* 密钥key
* 用户名
*/
private String accessKey;
/**
* 密钥密
* 密码
*/
private String accessKeySecret;
/**
* 端点
* 访问端点
*/
private String endpoint;
/**
......@@ -26,7 +32,11 @@ public class OssProperties {
*/
private String bucketName;
/**
* 说明
* 区域
*/
private String domain;
private String region;
/**
* path-style
*/
private Boolean pathStyleAccessEnabled = true;
}
package com.central.oss.service;
import com.central.oss.model.ObjectInfo;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.io.OutputStream;
/**
* @author zlt
* @date 2021/2/9
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
public interface IOssService {
/**
* 上传对象
* @param objectName 对象名
* @param is 对象流
*/
ObjectInfo upload(String objectName, InputStream is);
/**
* 上传对象
* @param file 对象
*/
ObjectInfo upload(MultipartFile file);
/**
* 删除对象
* @param objectKey 对象标识
*/
void delete(String objectKey);
/**
* 查看文件
* @param objectPath 对象路径
* @param os 输出流
*/
void view(String objectPath, OutputStream os);
}
package com.central.oss.template;
import com.central.oss.model.ObjectInfo;
import com.central.oss.properties.FileServerProperties;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadCallback;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import lombok.SneakyThrows;
import org.apache.commons.io.FilenameUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.InputStream;
/**
* FastDFS配置
*
* @author zlt
* @date 2021/2/11
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@ConditionalOnClass(FastFileStorageClient.class)
@ConditionalOnProperty(prefix = FileServerProperties.PREFIX, name = "type", havingValue = FileServerProperties.TYPE_FDFS)
public class FdfsTemplate {
@Resource
private FileServerProperties fileProperties;
@Resource
private FastFileStorageClient storageClient;
@SneakyThrows
public ObjectInfo upload(String objectName, InputStream is) {
return upload(objectName, is, is.available());
}
@SneakyThrows
public ObjectInfo upload(MultipartFile file) {
return upload(file.getOriginalFilename(), file.getInputStream(), file.getSize());
}
/**
* 上传对象
* @param objectName 对象名
* @param is 对象流
* @param size 大小
*/
private ObjectInfo upload(String objectName, InputStream is, long size) {
StorePath storePath = storageClient.uploadFile(is, size, FilenameUtils.getExtension(objectName), null);
ObjectInfo obj = new ObjectInfo();
obj.setObjectPath(storePath.getFullPath());
obj.setObjectUrl("http://" + fileProperties.getFdfs().getWebUrl() + "/" + storePath.getFullPath());
return obj;
}
/**
* 删除对象
* @param objectPath 对象路径
*/
public void delete(String objectPath) {
if (!StringUtils.isEmpty(objectPath)) {
StorePath storePath = StorePath.parseFromUrl(objectPath);
storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
}
}
/**
* 下载对象
* @param objectPath 对象路径
* @param callback 回调
*/
public <T> T download(String objectPath, DownloadCallback<T> callback) {
if (!StringUtils.isEmpty(objectPath)) {
StorePath storePath = StorePath.parseFromUrl(objectPath);
return storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), callback);
}
return null;
}
}
package com.central.oss.template;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectInputStream;
import com.amazonaws.util.IOUtils;
import com.central.oss.model.ObjectInfo;
import com.central.oss.properties.FileServerProperties;
import lombok.SneakyThrows;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Calendar;
/**
* aws s3配置
*
* @author zlt
* @date 2021/2/11
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@ConditionalOnClass(AmazonS3.class)
@ConditionalOnProperty(prefix = FileServerProperties.PREFIX, name = "type", havingValue = FileServerProperties.TYPE_S3)
public class S3Template implements InitializingBean {
private static final String DEF_CONTEXT_TYPE = "application/octet-stream";
private static final String PATH_SPLIT = "/";
@Autowired
private FileServerProperties fileProperties;
private AmazonS3 amazonS3;
@Override
public void afterPropertiesSet() {
ClientConfiguration config = new ClientConfiguration();
AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration(fileProperties.getS3().getEndpoint(), fileProperties.getS3().getRegion());
AWSCredentials credentials = new BasicAWSCredentials(fileProperties.getS3().getAccessKey(), fileProperties.getS3().getAccessKeySecret());
AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(credentials);
this.amazonS3 = AmazonS3Client.builder()
.withEndpointConfiguration(endpoint)
.withClientConfiguration(config)
.withCredentials(awsCredentialsProvider)
.withPathStyleAccessEnabled(fileProperties.getS3().getPathStyleAccessEnabled())
.disableChunkedEncoding()
.build();
}
@SneakyThrows
public ObjectInfo upload(String fileName, InputStream is) {
return upload(fileProperties.getS3().getBucketName(), fileName, is, is.available(), DEF_CONTEXT_TYPE);
}
@SneakyThrows
public ObjectInfo upload(MultipartFile file) {
return upload(fileProperties.getS3().getBucketName(), file.getOriginalFilename(), file.getInputStream()
, ((Long)file.getSize()).intValue(), file.getContentType());
}
@SneakyThrows
public ObjectInfo upload(String bucketName, String fileName, InputStream is) {
return upload(bucketName, fileName, is, is.available(), DEF_CONTEXT_TYPE);
}
/**
* 上传对象
* @param bucketName bucket名称
* @param objectName 对象名
* @param is 对象流
* @param size 大小
* @param contentType 类型
*/
private ObjectInfo upload(String bucketName, String objectName, InputStream is, int size, String contentType) {
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(size);
objectMetadata.setContentType(contentType);
PutObjectRequest putObjectRequest = new PutObjectRequest(
bucketName, objectName, is, objectMetadata);
putObjectRequest.getRequestClientOptions().setReadLimit(size + 1);
amazonS3.putObject(putObjectRequest);
ObjectInfo obj = new ObjectInfo();
obj.setObjectPath(bucketName + PATH_SPLIT + objectName);
obj.setObjectUrl(fileProperties.getS3().getEndpoint() + PATH_SPLIT + obj.getObjectPath());
return obj;
}
public void delete(String objectName) {
delete(fileProperties.getS3().getBucketName(), objectName);
}
public void delete(String bucketName, String objectName) {
amazonS3.deleteObject(bucketName, objectName);
}
/**
* 获取预览地址
* @param bucketName bucket名称
* @param objectName 对象名
* @param expires 有效时间(分钟),最大7天有效
* @return
*/
public String getViewUrl(String bucketName, String objectName, int expires) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MINUTE, expires);
URL url = amazonS3.generatePresignedUrl(bucketName, objectName, cal.getTime());
return url.toString();
}
public void out(String objectName, OutputStream os) {
out(fileProperties.getS3().getBucketName(), objectName, os);
}
/**
* 输出对象
* @param bucketName bucket名称
* @param objectName 对象名
* @param os 输出流
*/
@SneakyThrows
public void out(String bucketName, String objectName, OutputStream os) {
S3Object s3Object = amazonS3.getObject(bucketName, objectName);
try (
S3ObjectInputStream s3is = s3Object.getObjectContent();
) {
IOUtils.copy(s3is, os);
}
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.central.oss.config.OssAutoConfigure
\ No newline at end of file
......@@ -21,6 +21,12 @@ zlt.sentinel.dashboard=192.168.28.130:6999
zlt.fdfs.web-url=192.168.28.130
zlt.fdfs.trackerList=${zlt.fdfs.web-url}:22122
##### s3配置
zlt.s3.access-key=minioadmin
zlt.s3.accessKeySecret=minioadmin
zlt.s3.endpoint=http://192.168.28.130:9000
zlt.s3.bucketName=test
##### 日志链路追踪
zlt.trace.enable=true
......
......@@ -21,5 +21,11 @@ zlt.sentinel.dashboard=192.168.28.130:6999
zlt.fdfs.web-url=192.168.28.130
zlt.fdfs.trackerList=${zlt.fdfs.web-url}:22122
##### s3配置
zlt.s3.access-key=minioadmin
zlt.s3.accessKeySecret=minioadmin
zlt.s3.endpoint=http://192.168.28.130:9000
zlt.s3.bucketName=test
##### 日志链路追踪
zlt.trace.enable=true
\ No newline at end of file
......@@ -21,5 +21,11 @@ zlt.sentinel.dashboard=192.168.28.130:6999
zlt.fdfs.web-url=192.168.28.130
zlt.fdfs.trackerList=${zlt.fdfs.web-url}:22122
##### s3配置
zlt.s3.access-key=minioadmin
zlt.s3.accessKeySecret=minioadmin
zlt.s3.endpoint=http://192.168.28.130:9000
zlt.s3.bucketName=test
##### 日志链路追踪
zlt.trace.enable=true
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册