亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot整合Minio實現(xiàn)文件上傳和讀取功能

 更新時間:2024年07月17日 09:45:11   作者:NEIL_XU_  
最近有一個需求是關于視頻上傳播放的,需要設計一個方案,中間談到了Minio這個技術,于是來學習一下,所以本文給大家介紹了SpringBoot整合Minio實現(xiàn)文件上傳和讀取功能,文中有詳細的代碼示例供大家參考,需要的朋友可以參考下

最近公司有一個需求是關于視頻上傳播放的,需要設計一個方案,中間談到了Minio這個技術,于是來學習一下

一、簡介

1.分布式文件系統(tǒng)應用場景

互聯(lián)網(wǎng)海量非結構化數(shù)據(jù)的存儲需求

  • 電商網(wǎng)絡:海量商品圖片
  • 視頻網(wǎng)站:海量視頻文件
  • 網(wǎng)盤:海量文件
  • 社交網(wǎng)站:海量圖片

2.Minio介紹

  • Go語言開發(fā),開源,免費的對象存儲服務,可以存儲海量非結構化的數(shù)據(jù),一個對象文件可以是任意大小,從幾kb到最大5T不等

3.Minio優(yōu)點

  • 部署簡單
  • 讀寫性能優(yōu)異
  • 支持海量存儲

二、docker部署(windows系統(tǒng))

這里我是用自己電腦(windows系統(tǒng))安裝了docker,然后使用docker來部署的

中文官網(wǎng)單節(jié)點多硬盤部署MinIO — MinIO中文文檔 | MinIO Container中文文檔

1.創(chuàng)建目錄

先進入D盤,創(chuàng)建docker的工作目錄 docker_workplace,再創(chuàng)建minio的目錄minio,再創(chuàng)建兩個文件夾dataconfig,如圖所示

在這里插入圖片描述

拉取鏡像,創(chuàng)建容器并運行

2.拉取鏡像

直接cmd,敲docker命令即可,和linux的語法一樣

在這里插入圖片描述

3.創(chuàng)建容器并運行

多行:

docker run -d --name minio \
--privileged=true \
--restart=always \
-p 9000:9000 -p 50000:50000 \
-e "MINIO_ROOT_USER=minio" \
-e "MINIO_ROOT_PASSWORD=miniominio" \
-v D:/docker_workplace/data/minio/config:/root/.minio \
-v D:/docker_workplace/data/minio/data1:/data1 \
-v D:/docker_workplace/data/minio/data2:/data2 \
-v D:/docker_workplace/data/minio/data3:/data3 \
-v D:/docker_workplace/data/minio/data4:/data4 \
minio/minio \
server \
--console-address ":50000" /data{1...4}

單行:

docker run -p 9000:9000 -p 50000:50000 -d --name minio -e "MINIO_ACCESS_KEY=minio" -e "MINIO_SECRET_KEY=miniominio" -v D:/docker_workplace/data/minio/config:/root/.minio -v D:/docker_workplace/data/minio/data1:/data1 -v D:/docker_workplace/data/minio/data2:/data2 -v D:/docker_workplace/data/minio/data3:/data3 -v D:/docker_workplace/data/minio/data4:/data4 --restart always minio/minio server --console-address ":50000" /data{1...4}

4.訪問控制臺

瀏覽器訪問:

http://localhost:50000/login

賬號/密碼(剛剛docker運行命令設置的):minio/miniominio

這里我第一次訪問失敗了,看了下docker日志,發(fā)現(xiàn)是賬號密碼長度不符合規(guī)范導致(一開始密碼是minio,達不到8個字符)

在這里插入圖片描述

于是改了密碼為miniominio,成功運行

在這里插入圖片描述

5.初始化配置

創(chuàng)建一個桶 Bucket

在這里插入圖片描述

這里出現(xiàn)了一個報錯,原因是說需要分布式部署才能使用,解決辦法:掛載多個卷

在這里插入圖片描述

在這里插入圖片描述

配置桶權限為public

在這里插入圖片描述

到這里,minio單機版就部署好了

三、Spring Boot整合Minio

1.創(chuàng)建demo項目

新建一個spring boot項目

2.引入依賴

<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.3.7</version>
</dependency>

3.配置

application.yml

spring:
  application:
    name: miniodemo
  servlet:
    multipart:
      # 文件上傳大小限制。超過該值直接報錯
      max-file-size: 20MB
      # 文件最大請求限制,用于批量上傳
      max-request-size: 20MB
  datasource:
    url: jdbc:mysql://localhost:3306/minio?useSSL=false&serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
# MinIO 配置
minio:
  endpoint: http://localhost:9000      # MinIO服務地址
  fileHost: http://localhost:9000      # 文件地址host
  bucketName: test                      # 存儲桶bucket名稱
  accessKey: minio                         # 用戶名
  secretKey: miniominio                     # 密碼
  imgSize: 20                           # 圖片大小限制,單位:m
  fileSize: 20                          # 文件大小限制,單位:m
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.xuyue.miniodemo.domain

4.編寫配置類

MinIOConfig.java

package com.xuyue.miniodemo.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration
@Data
public class MinIOConfig {

    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${minio.fileHost}")
    private String fileHost;
    @Value("${minio.bucketName}")
    private String bucketName;
    @Value("${minio.accessKey}")
    private String accessKey;
    @Value("${minio.secretKey}")
    private String secretKey;

    @Value("${minio.imgSize}")
    private Integer imgSize;
    @Value("${minio.fileSize}")
    private Integer fileSize;

}

5.MinIO工具類

MinIoUploadService.java

package com.xuyue.miniodemo.service;

import com.xuyue.miniodemo.config.MinIOConfig;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

/**
 * MinIO工具類
 */
@Slf4j
@Service
public class MinIoUploadService {

    @Resource
    private MinIOConfig minIOConfig;

    private MinioClient minioClient;

    private String endpoint;
    private String bucketName;
    private String accessKey;
    private String secretKey;
    private Integer imgSize;
    private Integer fileSize;


    private final String SEPARATOR = "/";

    @PostConstruct
    public void init() {
        this.endpoint = minIOConfig.getEndpoint();
        this.bucketName = minIOConfig.getBucketName();
        this.accessKey = minIOConfig.getAccessKey();
        this.secretKey = minIOConfig.getSecretKey();
        this.imgSize = minIOConfig.getImgSize();
        this.fileSize = minIOConfig.getFileSize();
        createMinioClient();
    }

    /**
     * 創(chuàng)建基于Java端的MinioClient
     */
    public void createMinioClient() {
        try {
            if (null == minioClient) {
                log.info("開始創(chuàng)建 MinioClient...");
                minioClient = MinioClient
                        .builder()
                        .endpoint(endpoint)
                        .credentials(accessKey, secretKey)
                        .build();
                createBucket(bucketName);
                log.info("創(chuàng)建完畢 MinioClient...");
            }
        } catch (Exception e) {
            log.error("MinIO服務器異常:{}", e);
        }
    }

    /**
     * 獲取上傳文件前綴路徑
     *
     * @return
     */
    public String getBasisUrl() {
        return endpoint + SEPARATOR + bucketName + SEPARATOR;
    }

    /******************************  Operate Bucket Start  ******************************/

    /**
     * 啟動SpringBoot容器的時候初始化Bucket
     * 如果沒有Bucket則創(chuàng)建
     *
     * @throws Exception
     */
    private void createBucket(String bucketName) throws Exception {
        if (!bucketExists(bucketName)) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 判斷Bucket是否存在,true:存在,false:不存在
     *
     * @return
     * @throws Exception
     */
    public boolean bucketExists(String bucketName) throws Exception {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }


    /**
     * 獲得Bucket的策略
     *
     * @param bucketName
     * @return
     * @throws Exception
     */
    public String getBucketPolicy(String bucketName) throws Exception {
        String bucketPolicy = minioClient
                .getBucketPolicy(
                        GetBucketPolicyArgs
                                .builder()
                                .bucket(bucketName)
                                .build()
                );
        return bucketPolicy;
    }


    /**
     * 獲得所有Bucket列表
     *
     * @return
     * @throws Exception
     */
    public List<Bucket> getAllBuckets() throws Exception {
        return minioClient.listBuckets();
    }

    /**
     * 根據(jù)bucketName獲取其相關信息
     *
     * @param bucketName
     * @return
     * @throws Exception
     */
    public Optional<Bucket> getBucket(String bucketName) throws Exception {
        return getAllBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
    }

    /**
     * 根據(jù)bucketName刪除Bucket,true:刪除成功; false:刪除失敗,文件或已不存在
     *
     * @param bucketName
     * @throws Exception
     */
    public void removeBucket(String bucketName) throws Exception {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
    }

    /******************************  Operate Bucket End  ******************************/


    /******************************  Operate Files Start  ******************************/

    /**
     * 判斷文件是否存在
     *
     * @param bucketName 存儲桶
     * @param objectName 文件名
     * @return
     */
    public boolean isObjectExist(String bucketName, String objectName) {
        boolean exist = true;
        try {
            minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
        } catch (Exception e) {
            exist = false;
        }
        return exist;
    }

    /**
     * 判斷文件夾是否存在
     *
     * @param bucketName 存儲桶
     * @param objectName 文件夾名稱
     * @return
     */
    public boolean isFolderExist(String bucketName, String objectName) {
        boolean exist = false;
        try {
            Iterable<Result<Item>> results = minioClient.listObjects(
                    ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(false).build());
            for (Result<Item> result : results) {
                Item item = result.get();
                if (item.isDir() && objectName.equals(item.objectName())) {
                    exist = true;
                }
            }
        } catch (Exception e) {
            exist = false;
        }
        return exist;
    }

    /**
     * 根據(jù)文件前綴查詢文件
     *
     * @param bucketName 存儲桶
     * @param prefix     前綴
     * @param recursive  是否使用遞歸查詢
     * @return MinioItem 列表
     * @throws Exception
     */
    public List<Item> getAllObjectsByPrefix(String bucketName,
                                            String prefix,
                                            boolean recursive) throws Exception {
        List<Item> list = new ArrayList<>();
        Iterable<Result<Item>> objectsIterator = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build());
        if (objectsIterator != null) {
            for (Result<Item> o : objectsIterator) {
                Item item = o.get();
                list.add(item);
            }
        }
        return list;
    }

    /**
     * 獲取文件流
     *
     * @param bucketName 存儲桶
     * @param objectName 文件名
     * @return 二進制流
     */
    public InputStream getObject(String bucketName, String objectName) throws Exception {
        return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /**
     * 斷點下載
     *
     * @param bucketName 存儲桶
     * @param objectName 文件名稱
     * @param offset     起始字節(jié)的位置
     * @param length     要讀取的長度
     * @return 二進制流
     */
    public InputStream getObject(String bucketName, String objectName, long offset, long length) throws Exception {
        return minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .offset(offset)
                        .length(length)
                        .build());
    }

    /**
     * 獲取路徑下文件列表
     *
     * @param bucketName 存儲桶
     * @param prefix     文件名稱
     * @param recursive  是否遞歸查找,false:模擬文件夾結構查找
     * @return 二進制流
     */
    public Iterable<Result<Item>> listObjects(String bucketName, String prefix,
                                              boolean recursive) {
        return minioClient.listObjects(
                ListObjectsArgs.builder()
                        .bucket(bucketName)
                        .prefix(prefix)
                        .recursive(recursive)
                        .build());
    }

    /**
     * 使用MultipartFile進行文件上傳
     *
     * @param bucketName  存儲桶
     * @param file        文件名
     * @param objectName  對象名
     * @param contentType 類型
     * @return
     * @throws Exception
     */
    public ObjectWriteResponse uploadFile(String bucketName, MultipartFile file,
                                          String objectName, String contentType) throws Exception {
        InputStream inputStream = file.getInputStream();
        return minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .contentType(contentType)
                        .stream(inputStream, inputStream.available(), -1)
                        .build());
    }

    /**
     * 上傳本地文件
     *
     * @param bucketName 存儲桶
     * @param objectName 對象名稱
     * @param fileName   本地文件路徑
     */
    public ObjectWriteResponse uploadFile(String bucketName, String objectName,
                                          String fileName) throws Exception {
        return minioClient.uploadObject(
                UploadObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .filename(fileName)
                        .build());
    }

    /**
     * 通過流上傳文件
     *
     * @param bucketName  存儲桶
     * @param objectName  文件對象
     * @param inputStream 文件流
     */
    public ObjectWriteResponse uploadFile(String bucketName, String objectName, InputStream inputStream) throws Exception {
        return minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(inputStream, inputStream.available(), -1)
                        .build());
    }

    /**
     * 創(chuàng)建文件夾或目錄
     *
     * @param bucketName 存儲桶
     * @param objectName 目錄路徑
     */
    public ObjectWriteResponse createDir(String bucketName, String objectName) throws Exception {
        return minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(new ByteArrayInputStream(new byte[]{}), 0, -1)
                        .build());
    }

    /**
     * 獲取文件信息, 如果拋出異常則說明文件不存在
     *
     * @param bucketName 存儲桶
     * @param objectName 文件名稱
     */
    public String getFileStatusInfo(String bucketName, String objectName) throws Exception {
        return minioClient.statObject(
                StatObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build()).toString();
    }

    /**
     * 拷貝文件
     *
     * @param bucketName    存儲桶
     * @param objectName    文件名
     * @param srcBucketName 目標存儲桶
     * @param srcObjectName 目標文件名
     */
    public ObjectWriteResponse copyFile(String bucketName, String objectName,
                                        String srcBucketName, String srcObjectName) throws Exception {
        return minioClient.copyObject(
                CopyObjectArgs.builder()
                        .source(CopySource.builder().bucket(bucketName).object(objectName).build())
                        .bucket(srcBucketName)
                        .object(srcObjectName)
                        .build());
    }

    /**
     * 刪除文件
     *
     * @param bucketName 存儲桶
     * @param objectName 文件名稱
     */
    public void removeFile(String bucketName, String objectName) throws Exception {
        minioClient.removeObject(
                RemoveObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build());
    }

    /**
     * 批量刪除文件
     *
     * @param bucketName 存儲桶
     * @param keys       需要刪除的文件列表
     * @return
     */
    public void removeFiles(String bucketName, List<String> keys) {
        List<DeleteObject> objects = new LinkedList<>();
        keys.forEach(s -> {
            objects.add(new DeleteObject(s));
            try {
                removeFile(bucketName, s);
            } catch (Exception e) {
                log.error("批量刪除失?。rror:{}", e);
            }
        });
    }

    /**
     * 獲取文件外鏈
     *
     * @param bucketName 存儲桶
     * @param objectName 文件名
     * @param expires    過期時間 <=7 秒 (外鏈有效時間(單位:秒))
     * @return url
     * @throws Exception
     */
    public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws Exception {
        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().expiry(expires).bucket(bucketName).object(objectName).build();
        return minioClient.getPresignedObjectUrl(args);
    }

    /**
     * 獲得文件外鏈
     *
     * @param bucketName
     * @param objectName
     * @return url
     * @throws Exception
     */
    public String getPresignedObjectUrl(String bucketName, String objectName) throws Exception {
        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .method(Method.GET).build();
        return minioClient.getPresignedObjectUrl(args);
    }

    /**
     * 將URLDecoder編碼轉成UTF8
     *
     * @param str
     * @return
     * @throws UnsupportedEncodingException
     */
    public String getUtf8ByURLDecoder(String str) throws UnsupportedEncodingException {
        String url = str.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
        return URLDecoder.decode(url, "UTF-8");
    }

    /******************************  Operate Files End  ******************************/


}

6.文件上傳

FileController.java

package com.xuyue.miniodemo.controller;

import com.xuyue.miniodemo.config.MinIOConfig;
import com.xuyue.miniodemo.service.MinIoUploadService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@Slf4j
public class FileController {
    @Autowired
    private MinIoUploadService minIoUploadService;
    @Autowired
    private MinIOConfig minIOConfig;

    /**
     * 上傳文件,返回url
     * @param file
     * @return
     * @throws Exception
     */
    @PostMapping("upload")
    public String upload(MultipartFile file) throws Exception {
        String fileName = file.getOriginalFilename();
        minIoUploadService.uploadFile(minIOConfig.getBucketName(), fileName, file.getInputStream());
        String imgUrl = minIOConfig.getFileHost()
                + "/"
                + minIOConfig.getBucketName()
                + "/"
                + fileName;

        return imgUrl;
    }

}

測試

啟動項目

使用postman請求接口,返回文件地址

在這里插入圖片描述

訪問地址:

在這里插入圖片描述

查看minio控制臺:

在這里插入圖片描述

以上就是SpringBoot整合Minio實現(xiàn)文件上傳和讀取功能的詳細內容,更多關于SpringBoot Minio文件上傳讀取的資料請關注腳本之家其它相關文章!

相關文章

  • jvm垃圾回收之GC調優(yōu)工具分析詳解

    jvm垃圾回收之GC調優(yōu)工具分析詳解

    這篇文章主要為大家介紹了jvm垃圾回收之GC調優(yōu)工具的分析詳解,在進行JVM?GC性能調優(yōu)之前,需要使用某些工具獲取到當前應用的狀態(tài)信息
    2022-01-01
  • JAVA編程不能不知道的反射用法總結

    JAVA編程不能不知道的反射用法總結

    這篇文章主要介紹了Java反射技術原理與用法,結合實例形式分析了Java反射技術的基本概念、功能、原理、用法及操作注意事項,需要的朋友可以參考下
    2021-07-07
  • JAVA ArrayList詳細介紹(示例)

    JAVA ArrayList詳細介紹(示例)

    本文對JAVA ArrayList做了詳細介紹,文中學到了ArrayList源碼解析、ArrayList遍歷方式、toArray()異常,最后給出了ArrayList示例。
    2013-11-11
  • java xml轉為json的n種方法

    java xml轉為json的n種方法

    本文給大家分享java xml轉為json的兩種方法,每種方法通過實例代碼給大家介紹的非常詳細,小編感覺第一種方法要比第二種方法好些,具體實現(xiàn)代碼跟隨小編一起看看吧
    2021-08-08
  • JAVA如何使用Math類操作數(shù)據(jù)

    JAVA如何使用Math類操作數(shù)據(jù)

    這篇文章主要介紹了JAVA如何使用Math類操作數(shù)據(jù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • JAVA collection集合之撲克牌游戲實例

    JAVA collection集合之撲克牌游戲實例

    本篇文章主要介紹了JAVA collection集合之撲克牌游戲實例,使用了collection集合開發(fā)小游戲,有需要的可以了解一下。
    2016-11-11
  • java怎么連接并訪問activemq

    java怎么連接并訪問activemq

    這篇文章主要介紹了java怎么連接并訪問activemq,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • Java判斷對象是否為空的四種方法小結

    Java判斷對象是否為空的四種方法小結

    這篇文章主要介紹了Java判斷對象是否為空的四種方法,判斷對象是否為空有多種方法,包括使用==或!=運算符直接比較對象與null,使用Objects.isNull()方法,以及用instanceof運算符或Optional類進行更安全的空值處理,需要的朋友可以參考下
    2024-10-10
  • Java常用集合之Set和Map的用法詳解

    Java常用集合之Set和Map的用法詳解

    這篇文章將通過一些示例為大家詳細介紹一下Java常用集合中Set和Map的用法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2022-07-07
  • 解決mybatis plus報錯com.microsoft.sqlserver.jdbc.SQLServerException:必須執(zhí)行該語句才能獲得結果

    解決mybatis plus報錯com.microsoft.sqlserver.jdbc.SQLServerE

    這篇文章主要介紹了解決mybatis plus報錯com.microsoft.sqlserver.jdbc.SQLServerException:必須執(zhí)行該語句才能獲得結果,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05

最新評論