- 项目中大多会遇到文件上传需求,通常我们会将一些图片、视频、文档等数据上传并存储在对象存储中
- 目前市面上用到的对象存储大多是阿里云的OSS(收费)、FastDFS(自己搭建繁琐)等
- 这里给大家分享一个搭建简单,使用方便,基于Apache License v2.0开源协议的对象存储系统,完全兼容Amazon S3接口的开源分布式对象存储-Minio。
1.简介
Minio对象存储系统是为海量数据存储、人工智能、大数据分析而设计,基于Apache License v2.0开源协议的对象存储系统,它完全兼容Amazon S3接口,单个对象最大可达5TB,适合存储海量图片、视频、日志文件、备份数据和容器/虚拟机镜像等。Minio主要采用Golang语言实现,整个系统都运行在操作系统的用户态空间,客户端与存储服务器之间采用http/https通信协议。
2.安装
2.1.使用Docker安装Minio
linux安装Docker可以参考我之前的文章:Linux安装Docker
2.1.1.拉取minio(最新版本坑多还不好用)
输入命令拉取minio老版本:
docker pull minio/minio:RELEASE.2021-06-17T00-10-46Z
使用命令 docker images 查看下载好的镜像。
2.1.2.启动minio(这里介绍的是单点启动)
请运行以下命令:
docker run -p 9000:9000 minio/minio:RELEASE.2021-06-17T00-10-46Z server /data
打开新的linux界面,查看minio服务是否启动,输入命令:
docker ps
2.1.3.访问minio
ip + 9000
2.1.4.MinIO自定义Access和Secret密钥
访问需要登录用户与秘钥,由于之前的minio运行命令太过简单,没有设置用户名、秘钥,所以要覆盖MinIO的自动生成的密钥,可以自己设置Access Key和Secret Key密钥:(命令加入 '-d' 表示后台运行)
docker run -d -p 9000:9000 --name minio\
-e "MINIO_ACCESS_KEY=minioadmin" \
-e "MINIO_SECRET_KEY=minioadmin" \
-v /usr/local/minio/data:/data \
-v /usr/local/minio/config:/root/.minio \
minio/minio:RELEASE.2021-06-17T00-10-46Z server /data
/usr/local/minio/data //数据卷存放路径
/usr/local/minio/config //服务配置文件
使用自己创建的用户、密码登录minio:
Unbelievable !!!!!!
3.使用
3.1.springboot项目中使用minio存储数据
3.1.1.引入minio的maven依赖
<!-- MiniO依赖 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.1</version>
</dependency>
3.1.2.在yml配置连接minio的地址、用户名、密码、存储桶名(上传文件所在的文件夹)
# minio链连接配置
minio:
endpoint: http://192.168.56.10:9000
accessKey: minioadmin
secretKey: minioadmin
bucketName: images
3.1.3.上传接口实现
import com.zhizai.cimzfbz.common.result.R;
import io.minio.*;
import io.minio.http.Method;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
@Api(tags = "minio存储")
@RestController
@RequestMapping("/minio")
public class MinioController {
private static final Logger LOGGER = LoggerFactory.getLogger(MinioController.class);
private static final String policyJson = "{"Version":"2012-10-17","Statement":" +
"[{"Action":["s3:GetBucketLocation","s3:ListBucket","s3:ListBucketMultipartUploads"]," +
""Effect":"Allow","Principal":{"AWS":["*"]},"Resource":["arn:aws:s3:::test"]," +
""Sid":""},{"Action":["s3:AbortMultipartUpload","s3:DeleteObject","s3:GetObject"," +
""s3:ListMultipartUploadParts","s3:PutObject"],"Effect":"Allow","Principal":{"AWS":["*"]}," +
""Resource":["arn:aws:s3:::test/*"],"Sid":""}]}";
@Value("${minio.endpoint}")
private String ENDPOINT;
@Value("${minio.bucketName}")
private String BUCKET_NAME;
@Value("${minio.accessKey}")
private String ACCESS_KEY;
@Value("${minio.secretKey}")
private String SECRET_KEY;
@ApiOperation("文件上传")
@PostMapping(value = "/upload")
public R upload1(@ApiParam(name = "file", value = "文件", required = true) @RequestParam MultipartFile file) {
try {
//创建一个Minio的Java客户端
MinioClient minioClient =
MinioClient.builder()
.endpoint(ENDPOINT)
.credentials(ACCESS_KEY, SECRET_KEY)
.build();
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(BUCKET_NAME).build());
if (found) {
LOGGER.info("存储桶已经存在!");
} else {
//创建存储桶并设置只读权限
minioClient.makeBucket(MakeBucketArgs.builder().bucket(BUCKET_NAME).build());
minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(BUCKET_NAME).config(policyJson).build());
}
String filename = file.getOriginalFilename();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
// 设置存储对象名称
String objectName = sdf.format(new Date()) + "/" + filename;
// 使用putObject上传一个文件到存储桶中
minioClient.putObject(PutObjectArgs.builder().bucket(BUCKET_NAME).object(objectName).stream(
file.getInputStream(), -1, 10485760)
.contentType(file.getContentType())
.build());
LOGGER.info("文件上传成功!");
//文件访问路径
String url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs
.builder()
.method(Method.GET)
.bucket(BUCKET_NAME)
.object(objectName)
.expiry(2, TimeUnit.HOURS)
.build());
//返回可以下载上传文件的访问路径
return R.ok().data("url", url).data("name", objectName).message("文件上传成功!");
} catch (Exception e) {
LOGGER.info("上传发生错误: {}!", e.getMessage());
return R.error().message("上传发生错误!");
}
}
@ApiOperation("文件删除")
@DeleteMapping(value = "/delete")
public R delete(@RequestParam("objectName") String objectName) {
try {
//创建一个Minio的Java客户端
MinioClient minioClient =
MinioClient.builder()
.endpoint(ENDPOINT)
.credentials(ACCESS_KEY, SECRET_KEY)
.build();
minioClient.removeObject(RemoveObjectArgs.builder().bucket(BUCKET_NAME).object(objectName).build());
} catch (Exception e) {
e.printStackTrace();
return R.ok().message("文件删除失败");
}
return R.ok().message("文件删除成功");
}
}
推荐大家去阅读官方文档,学习更多技能:docs.minio.org.cn/docs/master…
大功告成ヽ( ̄▽ ̄)و