跳至主要內容

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-testFile转为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参数一定放在最后!

参考文档

适用于与Amazon S3兼容的云存储的MinIO Java SDKopen in new window

Java Client API参考文档open in new window

代码样例open in new window