Java使用MinIO及SpringBoot集成

简介

MinIO Java Client SDK提供简单的API来访问任何与Amazon S3兼容的对象存储服务。
官方demo: https://github.com/minio/minio-java
官方文档:https://docs.min.io/docs/java-client-api-reference.html
普通Java集成

第一步

引入pom.xml依赖。

<!-- MinIO 依赖 -->
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.3.3</version>
</dependency>
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.0</version>
</dependency>

第二步

测试类:

package com.example.demo.minio;

import io.minio.*;
import io.minio.errors.MinioException;

import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @author :Mall
 * @date :Created in 2021-11-24
 * @description :
 */
public class FileUploader {

    public static void main(String[] args) {
        MinioClient minioClient =
                MinioClient.builder()
                        .endpoint("http://127.0.0.1:9000")
                        .credentials("admin", "maluole123")
                        .build();

        //upload(minioClient, "asiatrip", "C:\\Users\\Administrator\\Desktop\\个人物品\\测试文件\\b.jpg", "d.jpg");
        downloadMinio(minioClient, "G://ddd.jpg", "asiatrip", "d.jpg");
    }

    /**
     * 上传
     *
     * @param minioClient
     */
    public static void upload(MinioClient minioClient, String bucketName, String source, String targetname) {
        try {
            // 如果不存在“asiatrip”存储桶,则生成“asiatrip”。
            boolean found =
                    minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!found) {
                // 创建一个 'asiatrip'存储桶
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            } else {
                System.out.println("Bucket 'asiatrip' already exists.");
            }

            // 将“c盘文件b.jpg”作为对象名“d.jpg”上传到'asiatrip'桶里
            minioClient.uploadObject(
                    UploadObjectArgs.builder()
                            .bucket(bucketName)
                            .object(targetname)
                            .filename(source)
                            .build());
        } catch (MinioException | IOException | InvalidKeyException | NoSuchAlgorithmException e) {
            System.out.println("Error occurred: " + e);
        }
    }

    /**
     * 删除
     *
     * @param fileName
     * @return
     * @throws Exception
     */
    public static void remove(MinioClient minioClient, String bucketName, String fileName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 下载
     *
     * @return
     */
    public static void downloadMinio(MinioClient minioClient, String savepath, String bucketName, String fileName) {
        try {
            InputStream stream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
            FileOutputStream fileOutputStream = new FileOutputStream(savepath);
            byte[] buf = new byte[1024];
            int bytesRead;
            while ((bytesRead = stream.read(buf, 0, buf.length)) >= 0) {
                fileOutputStream.write(buf, 0, bytesRead);
                fileOutputStream.flush();
            }
            fileOutputStream.close();
            stream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

封装的Util工具类:

package com.example.demo.minio;

import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import io.minio.messages.Item;

import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.util.*;

/**
 * @author :Mall
 * @date :Created in 2021-11-26
 * @description :MinIO工具类
 * <p>
 * 为保证代码维护性,如需修改或使用遇到问题,请与作者联系。
 * 支持MinIO 8.3.X
 * </p>
 */
public class JavaMinIOUtil {
    //MinIO的API请求地址
    private final static String ENDPOINT = "http://192.168.1.86:90";
    //用户名
    private final static String USERNAME = "admin";
    //密码
    private final static String PASSWORD = "12345678";
    //单例加载
    private final static MinioClient minioClient = MinioClient.builder().endpoint(ENDPOINT).credentials(USERNAME, PASSWORD).build();


    /**
     * 创建桶,如果不存在则创建,存在跳过
     *
     * @param bucketName
     */
    public static void createBucket(String bucketName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (!found) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 获取桶列表
     *
     * @returnF
     */
    public static List<Bucket> findBucketList() {
        try {
            return minioClient.listBuckets();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        } catch (ErrorResponseException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidResponseException e) {
            e.printStackTrace();
            return null;
        } catch (ServerException e) {
            e.printStackTrace();
            return null;
        } catch (InsufficientDataException e) {
            e.printStackTrace();
            return null;
        } catch (XmlParserException e) {
            e.printStackTrace();
            return null;
        } catch (InternalException e) {
            e.printStackTrace();
            return null;
        } catch (IOException ioException) {
            ioException.printStackTrace();
            return null;
        }
    }

    /**
     * 根据桶名称,获取对象列表
     *
     * @param bucketName 桶名称
     * @param path       桶路径 .如 aaa文件夹则传入  aaa/
     * @return
     */
    public static List<Item> findObjectList(String bucketName, String path) {
        try {
            createBucket(bucketName);
            Iterable<Result<Item>> myObjects = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(path).build());
            Iterator<Result<Item>> iterator = myObjects.iterator();
            List<Item> list = new ArrayList<>();
            while (iterator.hasNext()) {
                list.add(iterator.next().get());
            }
            return list;
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        } catch (ErrorResponseException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidResponseException e) {
            e.printStackTrace();
            return null;
        } catch (ServerException e) {
            e.printStackTrace();
            return null;
        } catch (InsufficientDataException e) {
            e.printStackTrace();
            return null;
        } catch (XmlParserException e) {
            e.printStackTrace();
            return null;
        } catch (InternalException e) {
            e.printStackTrace();
            return null;
        } catch (IOException ioException) {
            ioException.printStackTrace();
            return null;
        }
    }

    /**
     * 文件状态,可查看是否存在
     *
     * @param bucketName 桶名称
     * @param filePath   上传的资源路径,保护名称。如果是根目录,就是文件名称
     * @return
     */
    public static StatObjectResponse getObjectState(String bucketName, String filePath) {
        try {
            createBucket(bucketName);
            return minioClient.statObject(
                    StatObjectArgs.builder().bucket(bucketName).object(filePath).build());
        } catch (MinioException | IOException | InvalidKeyException | NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 上传文件
     *
     * @param bucketName 桶名称
     * @param file       上传资源
     * @param filePath   上传的资源路径,保护名称。如果是根目录,就是文件名称
     * @return
     */
    public static boolean upload(String bucketName, InputStream file, String filePath) {
        try {
            createBucket(bucketName);
            minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(filePath).stream(file, file.available(), -1).build());
            return true;
        } catch (MinioException | IOException | InvalidKeyException | NoSuchAlgorithmException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 下载文件
     *
     * @param bucketName 桶名称
     * @param filePath   上传的资源路径,保护名称。如果是根目录,就是文件名称
     * @return
     */
    public static InputStream download(String bucketName, String filePath) {
        try {
            createBucket(bucketName);
            return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(filePath).build());
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        } catch (ErrorResponseException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidResponseException e) {
            e.printStackTrace();
            return null;
        } catch (ServerException e) {
            e.printStackTrace();
            return null;
        } catch (InsufficientDataException e) {
            e.printStackTrace();
            return null;
        } catch (XmlParserException e) {
            e.printStackTrace();
            return null;
        } catch (InternalException e) {
            e.printStackTrace();
            return null;
        } catch (IOException ioException) {
            ioException.printStackTrace();
            return null;
        }
    }

    /**
     * 删除文件
     *
     * @param bucketName 桶名称
     * @param filePath   资源名称
     * @return
     */
    public static boolean remove(String bucketName, String filePath) {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder().bucket(bucketName).object(filePath).build());
            return true;
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            return false;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return false;
        } catch (ErrorResponseException e) {
            e.printStackTrace();
            return false;
        } catch (InvalidResponseException e) {
            e.printStackTrace();
            return false;
        } catch (ServerException e) {
            e.printStackTrace();
            return false;
        } catch (InsufficientDataException e) {
            e.printStackTrace();
            return false;
        } catch (XmlParserException e) {
            e.printStackTrace();
            return false;
        } catch (InternalException e) {
            e.printStackTrace();
            return false;
        } catch (IOException ioException) {
            ioException.printStackTrace();
            return false;
        }

    }

    /**
     * 文件大小转换
     *
     * @param fileSize 文件大小,单位b
     * @return
     */
    private static String formatFileSize(long fileSize) {
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString = "";
        String wrongSize = "0B";
        if (fileSize == 0) {
            return wrongSize;
        }
        if (fileSize < 1024) {
            fileSizeString = df.format((double) fileSize) + " B";
        } else if (fileSize < 1048576) {
            fileSizeString = df.format((double) fileSize / 1024) + " KB";
        } else if (fileSize < 1073741824) {
            fileSizeString = df.format((double) fileSize / 1048576) + " MB";
        } else {
            fileSizeString = df.format((double) fileSize / 1073741824) + " GB";
        }
        return fileSizeString;
    }

    public static void main(String[] args) throws Exception {
        FileInputStream fileInputStream = new FileInputStream(new File("G:/a.jpg"));
        //上传
        //upload("bucket02", fileInputStream, "ccc.jpg");
        //下载
        //InputStream inputStream = download("bucket02", "ccc.jpg");
        //IOUtils.copy(inputStream, new FileOutputStream(new File("G:/ddd.jpg")));
        //删除
        //remove("bucket02", "ccc.jpg");
        //查看文件状态
        //StatObjectResponse statObject = getObjectState("bucket02", "b.jpg");


        //获取所有桶
        //findBucketList().stream().forEach(item -> System.out.println(item.name()));
        //获取桶根目录所有对象
        //findObjectList("bucket02", "aaa/").stream().forEach(item -> System.out.println(item.objectName()));
    }
}

SpringBoot集成

第一步

引入pom.xml依赖。

<!-- MinIO 依赖 -->
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.3.3</version>
</dependency>
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.0</version>
</dependency>

第二步

配置application.yml文件

minio:
  endpoint: http://192.168.1.86:90
  username: admin
  password: 12345678
  bucketname: bucket02

第三步

增加MinIOConfig配置类。

package com.example.demo.minio;

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author :Mall
 * @date :Created in 2021-11-26
 * @description :MinIO配置类
 */
@Configuration
public class MinIOConfig {
    //MinIO的API地址
    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${minio.username}")
    private String username;
    @Value("${minio.password}")
    private String password;

    @Bean
    public MinioClient minioClient() {
        return MinioClient.builder().endpoint(endpoint).credentials(username, password).build();
    }
}

第四步

增加MinIOUtil工具类

package com.example.demo.minio;

import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author :Mall
 * @date :Created in 2021-11-26
 * @description :MinIO工具类
 * <p>
 * 为保证代码维护性,如需修改或使用遇到问题,请与作者联系。
 * 支持MinIO 8.3.X
 * </p>
 */
@Component
public class MinIOUtil {
    @Autowired
    private MinioClient minioClient;

    @Value("${minio.bucketname}")
    private String bucketName;

    /**
     * 创建桶,如果不存在则创建,存在跳过
     */
    public void createBucket() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (!found) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 获取桶列表
     *
     * @returnF
     */
    public List<Bucket> findBucketList() {
        try {
            return minioClient.listBuckets();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        } catch (ErrorResponseException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidResponseException e) {
            e.printStackTrace();
            return null;
        } catch (ServerException e) {
            e.printStackTrace();
            return null;
        } catch (InsufficientDataException e) {
            e.printStackTrace();
            return null;
        } catch (XmlParserException e) {
            e.printStackTrace();
            return null;
        } catch (InternalException e) {
            e.printStackTrace();
            return null;
        } catch (IOException ioException) {
            ioException.printStackTrace();
            return null;
        }
    }

    /**
     * 根据桶名称,获取对象列表
     *
     * @param path 桶路径
     * @return
     */
    public List<Item> findObjectList(String path) {
        try {
            createBucket();
            Iterable<Result<Item>> myObjects = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());
            Iterator<Result<Item>> iterator = myObjects.iterator();
            List<Item> list = new ArrayList<>();
            while (iterator.hasNext()) {
                list.add(iterator.next().get());
            }
            return list;
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        } catch (ErrorResponseException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidResponseException e) {
            e.printStackTrace();
            return null;
        } catch (ServerException e) {
            e.printStackTrace();
            return null;
        } catch (InsufficientDataException e) {
            e.printStackTrace();
            return null;
        } catch (XmlParserException e) {
            e.printStackTrace();
            return null;
        } catch (InternalException e) {
            e.printStackTrace();
            return null;
        } catch (IOException ioException) {
            ioException.printStackTrace();
            return null;
        }
    }

    /**
     * 文件状态,可查看是否存在
     *
     * @param filePath 上传的资源路径,保护名称。如果是根目录,就是文件名称
     * @return
     */
    public StatObjectResponse getObjectState(String filePath) {
        try {
            createBucket();
            return minioClient.statObject(
                    StatObjectArgs.builder().bucket(bucketName).object(filePath).build());
        } catch (MinioException | IOException | InvalidKeyException | NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 上传文件
     *
     * @param file     上传资源
     * @param filePath 上传的资源路径,保护名称。如果是根目录,就是文件名称
     * @return
     */
    public boolean upload(InputStream file, String filePath) {
        try {
            createBucket();
            minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(filePath).stream(file, file.available(), -1).build());
            return true;
        } catch (MinioException | IOException | InvalidKeyException | NoSuchAlgorithmException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 下载文件
     *
     * @param filePath 上传的资源路径,保护名称。如果是根目录,就是文件名称
     * @return
     */
    public InputStream download(String filePath) {
        try {
            createBucket();
            return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(filePath).build());
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        } catch (ErrorResponseException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidResponseException e) {
            e.printStackTrace();
            return null;
        } catch (ServerException e) {
            e.printStackTrace();
            return null;
        } catch (InsufficientDataException e) {
            e.printStackTrace();
            return null;
        } catch (XmlParserException e) {
            e.printStackTrace();
            return null;
        } catch (InternalException e) {
            e.printStackTrace();
            return null;
        } catch (IOException ioException) {
            ioException.printStackTrace();
            return null;
        }
    }

    /**
     * 删除文件
     *
     * @param filePath 资源名称
     * @return
     */
    public boolean remove(String filePath) {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder().bucket(bucketName).object(filePath).build());
            return true;
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            return false;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return false;
        } catch (ErrorResponseException e) {
            e.printStackTrace();
            return false;
        } catch (InvalidResponseException e) {
            e.printStackTrace();
            return false;
        } catch (ServerException e) {
            e.printStackTrace();
            return false;
        } catch (InsufficientDataException e) {
            e.printStackTrace();
            return false;
        } catch (XmlParserException e) {
            e.printStackTrace();
            return false;
        } catch (InternalException e) {
            e.printStackTrace();
            return false;
        } catch (IOException ioException) {
            ioException.printStackTrace();
            return false;
        }

    }

    /**
     * 文件大小转换
     *
     * @param fileSize 文件大小,单位b
     * @return
     */
    public String formatFileSize(long fileSize) {
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString = "";
        String wrongSize = "0B";
        if (fileSize == 0) {
            return wrongSize;
        }
        if (fileSize < 1024) {
            fileSizeString = df.format((double) fileSize) + " B";
        } else if (fileSize < 1048576) {
            fileSizeString = df.format((double) fileSize / 1024) + " KB";
        } else if (fileSize < 1073741824) {
            fileSizeString = df.format((double) fileSize / 1048576) + " MB";
        } else {
            fileSizeString = df.format((double) fileSize / 1073741824) + " GB";
        }
        return fileSizeString;
    }
}

第五步

增加测试Controller实现功能。

package com.example.demo.controller;

import com.example.demo.minio.MinIOUtil;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.minio.StatObjectResponse;
import io.minio.messages.Bucket;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author :Mall
 * @date :Created in 2021-11-26
 * @description :
 */
@RestController()
@RequestMapping("/minio")
public class MinIOController {
    @Autowired
    private MinIOUtil minIOUtil;

    /**
     * Bucket列表
     *
     * @return
     */
    @RequestMapping("/bucketlist")
    public List<Map<String, String>> bucketlist() {
        List<Map<String, String>> list = new ArrayList<>();
        minIOUtil.findBucketList().stream().forEach(item -> {
            Map<String, String> map = new HashMap<>();
            map.put("name", item.name());
            map.put("date", item.creationDate().toString());
            list.add(map);
        });
        return list;
    }

    /**
     * 根据路径获取对象列表
     *
     * @param path
     * @return
     */
    @RequestMapping("/findObjectList")
    public List<Map<String, String>> findObjectList(String path) {
        List<Map<String, String>> list = new ArrayList<>();
        minIOUtil.findObjectList(path).stream().forEach(item -> {
            Map<String, String> map = new HashMap<>();
            map.put("name", item.objectName());
            map.put("size", minIOUtil.formatFileSize(item.size()));
            list.add(map);
        });
        return list;
    }

    /**
     * 上传文件
     */

    @RequestMapping("/upload")
    public void upload(@RequestParam(name = "file", required = false) MultipartFile[] file) throws IOException {
        for (MultipartFile multipartFile : file) {
            minIOUtil.upload(multipartFile.getInputStream(), multipartFile.getOriginalFilename());
        }
    }

    /**
     * 下载文件
     */

    @RequestMapping("/download")
    public void download(HttpServletResponse response, String filename) throws IOException {
        InputStream download = minIOUtil.download(filename);
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
        IOUtils.copy(download, response.getOutputStream());
    }

    /**
     * 删除文件
     */

    @RequestMapping("/remove")
    public void remove(HttpServletResponse response, String filepath) throws IOException {
        minIOUtil.remove(filepath);
    }

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铁蛋的铁,铁蛋的蛋

留一杯咖啡钱给作者吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值