使用springboot+mysql+minio+nacos做个自己的OSS微服务
本文皆为个人原创,请尊重创作,未经许可不得转载。
什么是OSS
OSS工作原理
数据以对象(Object)的形式存储在OSS的存储空间(Bucket )中。如果要使用OSS存储数据,您需要先创建Bucket,并指定Bucket的地域、访问权限、存储类型等属性。创建Bucket后,您可以将数据以Object的形式上传到Bucket,并指定Object的文件名(Key)作为其唯一标识。
OSS以HTTP RESTful API的形式对外提供服务,访问不同地域需要不同的访问域名(Endpoint)。当您请求访问OSS时,OSS通过使用访问密钥(AccessKey ID和AccessKey Secret)对称加密的方法来验证某个请求的发送者身份。
来源:阿里云help.aliyun.com/zh/oss/prod…
minio
MinIO 是一种高性能、S3 兼容的对象存储。 它专为大规模 AI/ML、数据湖和数据库工作负载而构建,并且它是由软件定义的存储。 不需要购买任何专有硬件,就可以在云上和普通硬件上拥有分布式对象存储。 MinIO拥有开源 GNU AGPL v3 和商业企业许可证的双重许可。
中文文档地址:www.minio.org.cn/docs/minio/…
项目
此项目已上传Github托管,欢迎提交PR或Issues。
集成
springboot 2.x
nacos 2.x
thumbnailator 0.4.9
mybatis-plus 3.4.1
minio 8.5.4
项目目录结构
├─createtable.txt # 建表语句
├─pom.xml
├─README.md
├─src
| ├─main
| | ├─resources
| | | ├─application.yml
| | | ├─bootstrap-exapmle.yml # 参考配置文件
| | | ├─bootstrap.yml #
| | | └logback.xml
| | ├─java
| | | ├─Application.java
| | | ├─com
| | | | ├─nott
| | | | | ├─minio
| | | | | | ├─MinioTemplate.java # 包装Minio的操作类
| | | | | | ├─propertie
| | | | | | | └MinioProp.java # minio属性配置
| | | | | ├─file
| | | | | | ├─service
| | | | | | | └FileService.java # oss服务层
| | | | | | ├─mapper
| | | | | | | └SysMinioFileMapper.java # oss数据交互层
| | | | | | ├─entity
| | | | | | | └SysMinioFile.java # oss实体
| | | | | | ├─controller
| | | | | | | └FileController.java # oss文件操作控制层
| | | | | ├─config
| | | | | | ├─CorsConfig.java
| | | | | | └MybatisPlusConfig.java
| | | | | ├─common
| | | | | | ├─CommonPageService.java # 简单的mybatis-plus条件构造生成
| | | | | | ├─ExceptionHandler.java
| | | | | | ├─R.java # 统一结果类
| | | | | | └ThreadPoolContext.java
具体实现
整个系统整合的就是与minio服务端交互、在数据库(mysql)生成对应文件记录的过程,交互时客户端使用文件记录的id进行操作。
MinioTemplate
public class MinioTemplate {
private final Logger log = LoggerFactory.getLogger(MinioTemplate.class);
private MinioClient client;
@Resource
private MinioProp minioProp;
@Value("${upload.maxSize}")
private long maxSize;
@Value("${upload.compress}")
private boolean compress;
@Value("${minio.autocreate}")
public boolean autoCreate;
public MinioClient getClient() throws Exception {
if (this.client == null) {
MinioClient minioClient =
MinioClient.builder()
.endpoint(minioProp.getUrl(), minioProp.getPort(), false)
.credentials(minioProp.getUsername(), minioProp.getPassword())
.build();
if (minioClient == null) {
throw new RuntimeException("链接远程Minio服务端失败");
}
this.client = minioClient;
}
boolean found = client.bucketExists(BucketExistsArgs.builder().bucket(minioProp.getBucket()).build());
if (!found) {
if (autoCreate) {
client.makeBucket(MakeBucketArgs.builder().bucket(minioProp.getBucket()).build());
log.info("Auto make bucket: {}", minioProp.getBucket());
} else {
throw new RuntimeException(String.format("没有找到Bucket:[%s]", minioProp.getBucket()));
}
}
return this.client;
}
// 上传
public String upload(MultipartFile file, String holderCode) throws Exception {
if (file == null) {
throw new RuntimeException("文件不能为空");
}
boolean isPic = this.isPicture(file);
String filePath = "";
String uuidFileName = UUID.randomUUID().toString();
if (StringUtils.isNotEmpty(holderCode)) {
filePath = holderCode + "/" + uuidFileName;
} else {
filePath = uuidFileName;
}
MinioClient minioClient = getClient();
// 如果是图片则压缩
if (isPic && compress) {
file = this.handlePicCompress(file);
}
InputStream inputStream = file.getInputStream();
minioClient.putObject(
PutObjectArgs.builder().bucket(minioProp.getBucket()).object(filePath)
.contentType(file.getContentType())
.stream(
inputStream, inputStream.available(), -1)
.build());
log.info("File {},Upload Bucket {}", uuidFileName, minioProp.getBucket());
return uuidFileName;
}
// 下载、删除 ...
}
FileController
提供oss中Http交互的功能
@RestController
@RequestMapping("file")
public class FileController {
@Resource
private FileService fileService;
@Resource
private CommonPageService<SysMinioFile> commonPageService;
@PostMapping("upload")
public R fileUpload(@RequestParam("file") MultipartFile file, String holderCode) throws Exception {
if (file == null) {
return R.failure("文件为空");
}
return R.okData(fileService.uploadFile(file, holderCode));
}
@RequestMapping("preview/{id}")
public R preview(@NotNull @PathVariable("id") String id) throws Exception {
String url = fileService.preview(id);
return R.okData(url);
}
...
启动minio服务
以Windows本地测试为例,先在本地运行minio服务端。
注:如果是第一次启动,需要设置minio的用户和密码。
$ minio.exe server testData --console-address :9090

启动输出
进入管理后台
启动nacos
运行nacos并创建对应的命名空间和配置文件

项目已创建供参考的配置文件,bootstrap-exapmle.yml
测试
测试上传接口
预览接口
下载接口
本文皆为个人原创,请尊重创作,未经许可不得转载。
转载自:https://juejin.cn/post/7362547971060056102