minio组件
大约 3 分钟常用组件对象存储
git地址:
http://10.16.202.103:8089/component/component-ser/minio-spring-boot-starter
放弃FastDFS选择MinIO的理由
- FastDFS的api操作复杂
- FastDFS不支持直接以http链接的形式访问文件,如果要实现此功能,需要额外使用其扩展的Nginx扩展模块。
- MinIO兼容Amazon S3 API 接口协议,是在全球范围内达到共识的对象存储的协议。我们目前使用MinIO并自己维护,以后如果想把对象存储放到云上,只要云厂商支持S3标准,那么可以做到代码无改动。
使用方式
导入依赖:
<dependency>
<groupId>com.gosci.tech</groupId>
<artifactId>minio-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
项目中添加配置:
minio:
access-key: 7hIsAA1UL1g9QqIV05Nl
secret-key: '993tL2ooQKWbgqCUkahgzVkS6I0divBwqpgFrjl8'
uploadEndpoint: http://10.16.129.46:7777
downloadEndpoint: http://10.16.129.46:7777
bucket: dev
介绍一下参数:
- ak和sk是创建minioClient必须的参数,可在minio可视化控制台生成管理。控制台地址:http://10.16.129.46:7776 (用户名/密码:
admin
/admin123
) - 这里将上传
Endpoint
和下载Endpoint
分开是因为上传使用内网地址就可以了,但是下载的话有可能需要把ip和端口映射到公网地址,所以进行一下区分,如果纯粹在内网使用的话这两个地址填一样的就可以 - bucket是上传的桶名,建议每个项目建自己的桶,并且开发环境、测试环境、正式环境也进行区分
桶操作Api示例
注入桶操作service:
@Autowired
private MinioBucketService minioBucketService;
创建桶
minioBucketService.makeBucket("bucketName");
列出所有的存储桶
List<Bucket> buckets = minioBucketService.listBuckets();
判断桶是否存在
boolean exists = minioBucketService.bucketExists("bucketName");
删除桶
minioBucketService.removeBucket("bucketName");
列出桶里的对象
List<Item> test = minioBucketService.listObjects("bucketName", "prefix", true, false);
参数说明:
- bucketName:存储桶名称
- prefix:对象名称的前缀
- recursive:是否递归查找
- useVersion1:如果是true, 使用版本1 REST API
获取桶策略
minioBucketService.getBucketPolicy("bucketName");
对象操作Api示例
注入对象操作service:
@Autowired
private MinioObjectService minioObjectService;
上传对象
模拟上传文件,这里先通过spring-test
将File
转为MultipartFile
,实际使用中直接上传的就是MultipartFile
不需要转换。
@Test
public void putObject() throws IOException {
File file = new File("F:\\macbook.jpg");
FileInputStream fileInputStream = new FileInputStream(file);
MockMultipartFile mockMultipartFile
= new MockMultipartFile("test1.jpg", "org.jpg", MediaType.IMAGE_JPEG_VALUE, fileInputStream);
//上传并生成一个带有时限的链接,单位为秒
System.out.println(minioObjectService.putObject(minioProperties.getBucket(), "/path1", "test.jpg",
mockMultipartFile, 30));
//上传并生成一个永久链接
System.out.println(minioObjectService.putObject(minioProperties.getBucket(), "/path1", "test.jpg",
mockMultipartFile));
}
注意,只有创建的桶属性为public时生成的永久链接才有用,否则虽然能生成但不生效,无法通过http链接访问。
下载对象
会直接通过HttpServletResponse
通过流下载文件。
@ApiOperation(value = "查询文件并下载", notes = "查询文件并下载")
@GetMapping("download")
public void download(@RequestParam("bucketName") String bucketName,
@RequestParam("objectName") String objectName,
HttpServletResponse httpServletResponse) {
minioObjectService.getObject(bucketName,objectName,httpServletResponse);
}
查看对象状态
@Test
void statObject() {
StatObjectResponse statObjectResponse = minioObjectService.statObject(minioProperties.getBucket(), "/path1/test.jpg");
log.info(statObjectResponse.toString());
}
结果:
ObjectStat{bucket=dev, object=/path1/test.jpg, last-modified=2023-10-01T13:17:08Z, size=223120}
删除对象
@Test
void removeObject() {
minioObjectService.removeObject(minioProperties.getBucket(),"/path1/test.jpg");
}
生成带有时效的http链接
生成一个给HTTP GET请求用的 presigned URL。浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
@Test
void presignedGetObject() {
String url = minioObjectService.getPresignedUrl(minioProperties.getBucket(), "path1/test.jpg", 3600);
log.info(url);
}
生成永久链接
前面说过,这个链接必须在桶为public
时才有用。
@Test
void getPublicUrl(){
String url = minioObjectService.getPublicUrl(minioProperties.getBucket(), "/path1/test.jpg");
log.info(url);
}
获取文件上传的链接
生成一个给前端用的上传链接,可以由前端自行上传对象。
@Test
void getUploadUrl() {
UploadUrlParam uploadUrlParam = new UploadUrlParam();
uploadUrlParam.setObjectName("ooo.jpg");
Map<String, String> formData = minioObjectService.getUploadUrl(uploadUrlParam);
log.info(JsonUtils.toPrettyString(formData));
}
生成后的签名信息:
{
"x-amz-date" : "20231002T034155Z",
"x-amz-signature" : "85aecb0dc18cc8bf5f1d94b5d7e00a54852f890ea4c69016f4fd1d4afa6deed5",
"x-amz-algorithm" : "AWS4-HMAC-SHA256",
"x-amz-credential" : "7hIsAA1UL1g9QqIV05Nl/20231002/us-east-1/s3/aws4_request",
"policy" : "eyJleHBpcmF0aW9uIjoiMjAyMy0xMC0wOVQwMzo0MTo1NS4zODBaIiwiY29uZGl0aW9ucyI6W1siZXEiLCIkYnVja2V0IiwiZGV2Il0sWyJlcSIsIiRrZXkiLCJvb28uanBnIl0sWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsMCwyMTQ3NDgzNjQ4XSxbImVxIiwiJHgtYW16LWFsZ29yaXRobSIsIkFXUzQtSE1BQy1TSEEyNTYiXSxbImVxIiwiJHgtYW16LWNyZWRlbnRpYWwiLCI3aElzQUExVUwxZzlRcUlWMDVObC8yMDIzMTAwMi91cy1lYXN0LTEvczMvYXdzNF9yZXF1ZXN0Il0sWyJlcSIsIiR4LWFtei1kYXRlIiwiMjAyMzEwMDJUMDM0MTU1WiJdXX0="
}
在postman模拟上传,把上面的信息复制到form-data
中:
注意上传的file参数一定放在最后!