SpringBoot專案整合MinIO

[奋斗]發表於2024-11-01

一、MinIO的下載安裝以及基本使用

1.下載地址:https://dl.min.io/server/minio/release/windows-amd64/minio.exe

2.下載好後需要手動建立【data】資料夾用於儲存Minio中的資料


3.在對應檔案路徑處,鍵入【cmd】 後設定MinIO的一些變數(第一次啟動需要配置)

set MINIO_ROOT_USER=admin

set MINIO_ROOT_PASSWORD=admin123

set MINIO_ACCESS_KEY=admin

set MINIO_SECRET_KEY=admin123

5.下面是我踩的坑,如果只設定了MINIO_ROOT_USER和MINIO_ROOT_PASSWORD的值,而不設定MINIO_ACCESS_KEY和MINIO_SECRET_KEY的值,當啟動minio服務的時候就會報以下異常:

6. 啟動minio服務

minio.exe server data

7.進入登入頁面後,輸入對應的使用者名稱和密碼,也就是之前設定的MINIO_ROOT_USER和MINIO_ROOT_PASSWORD的值。

8. 進入主介面後,點選左側導航欄中的Buckets,然後點選Create Bucket。

9.進入該桶,點選upload,上傳一個檔案

10.點選左側導航欄中的Buckets,進入該桶,修改許可權為public,這樣外界就可以訪問上傳的檔案了。

桶的預設許可權是private,所以外界訪問不到,需要修改訪問許可權為public,但是要注意安全問題

二. SpringBoot整合MinIO

1.引入依賴

<dependency>
  <groupId>io.minio</groupId>
  <artifactId>minio</artifactId>
  <version>7.0.2</version>
</dependency>
<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <version>1.18.20</version>
</dependency>

2.編寫配置檔案

server:
 port: 8080
spring:
 # 配置檔案上傳大小限制
 servlet:
  multipart:
   max-file-size: 200MB
   max-request-size: 200MB
minio:
 host: http://127.0.0.1:9000 # 訪問地址
 url: ${minio.host}/${minio.bucket}/  # 物件儲存服務的url
 access-key: minioadmin # 登入賬號
 secret-key: minioadmin # 登入賬號密碼
 bucketName: test-bucket # 檔案桶的名稱
 bucket: public  // 許可權

3.編寫minio配置類

@Configuration
public class MinIoClientConfig {
    /**
     * minio配置
     */
    @Value("${minio.url}")
    private String endpoint;
    @Value("${minio.accessKey}")
    private String accessKey;
    @Value("${minio.secretKey}")
    private String secretKey;
    @Value("${minio.bucketName}")
    private String bucketName;

    /**
     * 注入minio客戶端
     *
     * @return minio客戶端物件
     */
    @Bean
    public MinioClient minioClient() {
        return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();
    }
}

4.編寫minio工具類

@Component
public class MinioUtil {

    /**
     * minio配置
     */
    @Value("${minio.url}")
    private String endpoint;

    @Autowired
    private MinioClient minioClient;
    
    /**
     * 建立一個桶
     */
    public void createBucket(String bucket) throws Exception {
        boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
        if (!found) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
        }
    }
    
    /**
     * 上傳一個檔案
     */
    public void uploadFile(InputStream stream, String bucket, String objectName) throws Exception {
        ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName)
                .stream(stream, -1, 10485760).build());

        System.out.println(objectWriteResponse.object() + " is uploaded successfully.");
    }
    
    /**
     * 列出所有的桶
     */
    public List<String> listBuckets() throws Exception {
        List<Bucket> list = minioClient.listBuckets();
        List<String> names = new ArrayList<>();
        list.forEach(b -> {
            names.add(b.name());
        });
        return names;
    }
    
    /**
     * 列出一個桶中的所有檔案和目錄
     */
    public List<Fileinfo> listFiles(String bucket) throws Exception {
        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucket).recursive(true).build());
            
            List<Fileinfo> infos = new ArrayList<>();
                results.forEach(r->{
                    Fileinfo info = new Fileinfo();
                    try {
                        Item item = r.get();
                        info.setFilename(item.objectName());
                        info.setDirectory(item.isDir());
                        info.setFilepath(endpoint+"/"+bucket+"/"+item.objectName());
                        infos.add(info);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
        return infos;
    }
    
    /**
     * 下載一個檔案
     */
    public InputStream download(String bucket, String objectName) throws Exception {
        InputStream stream = minioClient.getObject(
                      GetObjectArgs.builder().bucket(bucket).object(objectName).build());
        return stream;
    }
    
    /**
     * 刪除一個桶
     */
    public void deleteBucket(String bucket) throws Exception {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
    }
    
    /**
     * 刪除一個物件
     */
    public void deleteObject(String bucket, String objectName) throws Exception {
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build());
    }


    /**
     * 複製檔案
     */
    public void copyObject(String sourceBucket, String sourceObject, String targetBucket, String targetObject) throws Exception {
        this.createBucket(targetBucket);
        minioClient.copyObject(CopyObjectArgs.builder().bucket(targetBucket).object(targetObject)
                .source(CopySource.builder().bucket(sourceBucket).object(sourceObject).build()).build());
    }

    /**
     * 獲取檔案資訊
     */
    public String getObjectInfo(String bucket, String objectName) throws Exception {
        return minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(objectName).build()).toString();

    }

    /**
     * 生成一個給HTTP GET請求用的presigned URL。
     * 瀏覽器/移動端的客戶端可以用這個URL進行下載,
     * 即使其所在的儲存桶是私有的。
     */
    public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws Exception {
        GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs
                .builder().bucket(bucketName).object(objectName).expiry(expires).method(Method.GET).build();
        return minioClient.getPresignedObjectUrl(build);
    }

    /**
     * 獲取minio中所有的檔案
     */
    public List<Fileinfo> listAllFile() throws Exception {
        List<String> list = this.listBuckets();
        List<Fileinfo> fileinfos = new ArrayList<>();
        for (String bucketName : list) {
            fileinfos.addAll(this.listFiles(bucketName));
        }
        return fileinfos;
    }
}

5.編寫檔案實體類

@Data
public class Fileinfo {
    String filename;
    String filepath;
    Boolean directory;
}

6.編寫介面響應實體

@Data
public class ResultData<T> {

    public static final Integer SUCCESS_CODE = 200;
    public static final Integer FAIL_CODE = 4000;
    public static final String SUCCESS_MESSAGE = "操作成功";
    public static final String FAIL_MESSAGE = "操作失敗";
    /**
     * 返回狀態碼
     */
    private Integer code;
    /**
     * 返回資訊
     */
    private String message;

    /**
     * 返回資料
     */
    private T data;


    public ResultData() {

    }

    public static <T> ResultData<T> success() {
        ResultData<T> resultUtil = new ResultData<>();
        resultUtil.setCode(SUCCESS_CODE);
        resultUtil.setMessage(SUCCESS_MESSAGE);
        return resultUtil;
    }

    public static <T> ResultData<T> success(T data) {
        ResultData<T> resultUtil = success();
        resultUtil.setData(data);
        return resultUtil;
    }

    public static <T> ResultData<T> success(String message, T data) {
        ResultData<T> resultUtil = success();
        resultUtil.setMessage(message);
        resultUtil.setData(data);
        return resultUtil;
    }

    public static <T> ResultData<T> success(Integer code, String message, T data) {
        ResultData<T> resultUtil = new ResultData<>();
        resultUtil.setCode(code);
        resultUtil.setMessage(message);
        resultUtil.setData(data);
        return resultUtil;
    }

    public static <T> ResultData<T> success(Integer code, String message,Integer count, T data) {
        ResultData<T> resultUtil = new ResultData<>();
        resultUtil.setCode(code);
        resultUtil.setMessage(message);
        resultUtil.setData(data);
        return resultUtil;
    }

    public static <T> ResultData<T> fail() {
        ResultData<T> resultUtil = new ResultData<>();
        resultUtil.setCode(FAIL_CODE);
        resultUtil.setMessage(FAIL_MESSAGE);
        return resultUtil;
    }

    public static <T> ResultData<T> fail(T data) {
        ResultData<T> resultUtil = fail();
        resultUtil.setData(data);
        return resultUtil;
    }

    public static <T> ResultData<T> fail(String message, T data) {
        ResultData<T> resultUtil = fail();
        resultUtil.setMessage(message);
        resultUtil.setData(data);
        return resultUtil;
    }

    public static <T> ResultData<T> fail(Integer code, String message) {
        ResultData<T> resultUtil = fail();
        resultUtil.setCode(code);
        resultUtil.setMessage(message);
        return resultUtil;
    }

    public static <T> ResultData<T> fail(Integer code, String message, T data) {
        ResultData<T> resultUtil = new ResultData<>();
        resultUtil.setCode(code);
        resultUtil.setMessage(message);
        resultUtil.setData(data);
        return resultUtil;
    }

    public void setCode(int code){
        this.code = code;
    }
    public int getCode(){
        return this.code;
    }
    public void setMessage(String message){
        this.message = message;
    }
    public String getMessage(){
        return message;
    }
    public void setData(T data){
        this.data = data;
    }
    public T getData(){
        return data;
    }
}

7.建立minio控制器

/**
 * minio相關介面
 *
 * @author songwp
 * @date 2024/11/11 11:28
 */
@RestController
@RequestMapping("minio")
public class MinioController {

    @Autowired
    MinioUtil minioUtil;


    /**
     * 檔案上傳
     *
     * @param file 檔案
     * @param bucket 桶名
     * @param objectName 物件名
     * @return 是否成功
     * @throws Exception
     */
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public ResultData upload(@RequestParam MultipartFile file,
                             @RequestParam String bucket,
                             @RequestParam(required = false) String objectName) throws Exception {
        minioUtil.createBucket(bucket);
        if (objectName != null) {
            minioUtil.uploadFile(file.getInputStream(), bucket, objectName + "/" + file.getOriginalFilename());
        } else {
            minioUtil.uploadFile(file.getInputStream(), bucket, file.getOriginalFilename());
        }
        return ResultData.success();
    }

    /**
     * 獲取檔案資訊
     * @param bucket 桶名
     * @return 是否成功
     */
    @RequestMapping(value = "/getFile", method = RequestMethod.GET)
    public ResultData getFile(@RequestParam ("bucket")String bucket){
        try {
            List<Fileinfo> fileinfos = minioUtil.listFiles(bucket);
            return ResultData.success(fileinfos);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 檔案下載
     *
     * @param bucket 桶名
     * @param objectName 物件名
     * @return 是否成功
     */
    @GetMapping("download")
    public ResultData download(@RequestParam("bucket") String bucket,
                               @RequestParam("objectName") String objectName){
        try {
            InputStream download = minioUtil.download(bucket, objectName);
            return ResultData.success();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 獲取檔案資訊
     *
     * @param bucket 桶名
     * @param objectName 物件名
     * @return 是否成功
     */
    @GetMapping("getObjectInfo")
    public ResultData getObjectInfo(@RequestParam("bucket") String bucket,
                               @RequestParam("objectName") String objectName) throws Exception {
        String objectInfo = minioUtil.getObjectInfo(bucket, objectName);
        String objectStat = objectInfo.replaceAll("ObjectStat", "");
        return ResultData.success(objectStat);
    }


    /**
     * 生成一個給HTTP GET請求用的presigned URL。
     *
     * @param bucket 桶名
     * @param objectName 物件名
     * @return 是否成功
     */
    @GetMapping("getObjectUrl")
    public ResultData getObjectUrl(@RequestParam("bucket") String bucket,
                                    @RequestParam("objectName") String objectName) throws Exception {
        String url = minioUtil.getPresignedObjectUrl(bucket, objectName,7200);
        return ResultData.success(url);
    }


    /**
     * 列出所有的桶
     */
    @RequestMapping(value = "/listBuckets", method = RequestMethod.GET)
    public ResultData listBuckets() throws Exception {
        return ResultData.success(minioUtil.listBuckets());
    }

    /**
     * 獲取minio中所有的檔案
     */
    @RequestMapping(value = "/listAllFile", method = RequestMethod.GET)
    public ResultData listAllFile() throws Exception {
        return ResultData.success(minioUtil.listAllFile());
    }
}

8.postman介面呼叫例項

9.最後檢視test-bucket桶中是否有剛才上傳的檔案就可以了。如果有則表明你的專案已經成功整合minio了

相關文章