當前位置: 妍妍網 > 碼農

SpringBoot + Minio 實作檔切片極速上傳技術(實戰典藏版)

2024-07-04碼農

大家好,我是磊哥。

一. 概述

提示:請不要多個部落格來回跳著看,此文章之詳細絕無僅有,融合多家之長,如果遇見報錯,請仔細捋一遍文章,不要忽略!我在寫的時候因為許多文章不全面,來回跳遇見許多坑,希望大家可以避免,本文章中悉數做了標註提醒!!!

官網地址:

https://min.io

文件地址:

https://docs.min.io

該文件源碼地址(免費資源):

https://download.csdn.net/download/weixin_53742691/87856930

Minio是一款開源的物件儲存伺服器,它可以執行在多種作業系統上,包括Linux、Windows和MacOS等。它提供了一種簡單、可延伸、高可用的物件儲存解決方案,支持多種數據格式,包括物件、塊和檔等。

以下是Minio的主要特點:

簡單易用: Minio的安裝和配置非常簡單,只需要下載並執行相應的二進制檔即可。它提供了一個Web UI,可以透過界面管理儲存桶和物件。

可延伸性: Minio可以輕松地擴充套件到多個節點,以提供高可用性和容錯能力。它支持多種部署模式,包括單節點、主從復制和集群等。

高可用性: Minio提供了多種機制來保證數據的可靠性和可用性,包括冗余備份、數據復制和故障轉移等。

安全性: Minio提供了多種安全機制來保護數據的機密性和完整性,包括SSL/TLS加密、存取控制和數據加密等。

多語言支持: Minio支持多種程式語言,包括Java、Python、Ruby和Go等。

社群支持: Minio是一個開源計畫,擁有龐大的社群支持和貢獻者。它的原始碼可以在GitHub上獲得,並且有一個活躍的信件列表和論壇。

物件儲存: Minio的核心功能是物件儲存。它允許使用者上傳和下載任意數量和大小的物件,並提供了多種API和SDK來存取這些物件。

塊儲存: Minio還支持塊儲存,允許使用者上傳和下載大型檔(例如影像或視訊)。塊儲存是一種快速、高效的方式來處理大型檔。

檔儲存: Minio還支持檔儲存,允許使用者上傳和下載單個檔。檔儲存是一種簡單、快速的方式來處理小型檔。

總之,Minio是一款強大、靈活、可延伸的物件儲存伺服器,適用於各種套用場景,包括雲端儲存、大數據儲存和物聯網等。

二. 套用場景

MinIO是一種高效能、擴充套件性好的物件儲存系統,它可以適用於許多套用場景,其中包括但不限於以下幾種:

大規模數據儲存: 由於MinIO使用分布式環境來儲存數據,因此可以輕松擴充套件以滿足需要管理大量數據的組織和企業的需求。

影像和媒體儲存: 由於MinIO對原始二進制數據進行了最佳化,因此非常適合儲存影像、音訊和視訊等媒體檔。它還支持WebP、JPEG和PNG等格式,可在多種裝置和瀏覽器上工作。

雲原生應用程式: MinIO是一個雲原生的物件儲存系統,可以與Kubernetes、Docker Swarm和Mesosphere等容器編排工具無縫整合,可以很好地滿足基於雲的應用程式的需求。

數據保護和災難恢復: MinIO的多副本寫入功能和內建的糾刪碼支持,使得數據備份和恢復變得簡單而強大。

分布式計算和機器學習: MinIO提供STS(S3 Select)和HDFS介面,支持在資料倉儲中直接執行SQL查詢和MapReduce等並列處理框架。這使得它成為用於Big Data、AI和ML等分布式計算任務的理想選擇。

需要註意的是,以上列出的套用場景並不是MinIO所有可適用的場景。具體取決於每個使用情況的細節和需求。

三. Minio實作分片上傳的主要步驟

使用SpringBoot和MinIO實作分片上傳、秒傳、續傳主要包含以下幾個步驟:

前端選擇檔並對其進行切割: 可以使用JavaScript等前端技術將檔切成多個片段,並為每個片段生成唯一標識。

將每個分片上傳到MinIO物件儲存: 呼叫MinIO的Java SDK將每個分片上傳到MinIO中,每個分片的KEY名稱包含基礎名稱和片段ID。

將所有分片合並成最終檔: 在前端完成所有分片的上傳之後,在後台開發一個介面,按照唯一標識將所有分片合並成最終檔。合並過程可以在套用伺服器上完成,也可以使用MinIO Object Storage本身的合並功能完成。

實作秒傳: 在前端上傳分片之前,透過請求後台介面來根據檔名稱和檔MD5值判斷該檔是否已經存在,如果存在則可以直接返回檔URL,即可實作秒傳。

實作續傳: 在前端上傳分片時出現了網路問題或客戶端故障導致檔上傳被中斷,這時候只需記錄已上傳的分片序列號和狀態標誌,從下一個分片重新開始上傳即可。

處理錯誤和異常: 在檔上傳過程中可能會遇到各種問題,比如服務故障、網路中斷、客戶端處理超時等。因此需要加入錯誤和例外處理,保證整個上傳過程順利進行。

總體而言,使用SpringBoot和MinIO實作分片上傳、秒傳、續傳的難度不算大,可以根據上述步驟進行開發和實作。

四. Centos7安裝Minio

建立目的檔夾

mkdir minio

使用docker檢視目標映像狀況

大家需要註意,此處我們首先需要安裝docker,對於相關安裝教程,大家可以檢視我之前的文章,按部就班就可以,此處不再贅述!!!

docker search minio

使用docker拉去映像

docker pull minio/minio

檢視映像是否拉取成功

docker images

啟動Minio容器

docker run -p 9000:9000 -p 9090:9090 --net=host --name minio -d --restart=always -e "MINIO_ACCESS_KEY=IT@WangHui" -e "MINIO_SECRET_KEY=IT@WangHui" minio/minio server /data --console-address ":9000" -address ":9090"

註意一下,對於密碼強度是有要求的,不然報錯

這是一個執行 MinIO 容器的 Docker 命令,具體參數解釋如下:

-p: 對映容器內部的埠到宿主機上。其中 9000 和 9090 分別對映到宿主機的 9000 和 9090 埠上。

--net=host: 將容器加入到主機網路中,共享宿主機的 IP 地址。

--name minio: 指定容器的名稱為 minio。

--restart=always: 設定容器在結束後自動重新啟動。

-e: 設定環境變量。這裏設定了兩個環境變量: MINIO_ACCESS_KEY MINIO_SECRET_KEY ,值分別為 IT@WangHui IT@WangHui

--mount: 將容器內部的目錄掛載到宿主機上。這裏將容器內的 /data 目錄掛載到了宿主機的 /data 目錄上。

--console-address: 指定容器的控制台地址。這裏設定為 :9000,表示可以透過宿主機上的 9000 埠存取容器的控制台。

-address: 指定容器的網路地址。這裏設定為 :9090,表示可以透過宿主機上的 9090 埠存取容器的服務。

提示:頁面存取9000,程式碼裏面9090

提示:頁面存取9000,程式碼裏面9090

提示:頁面存取9000,程式碼裏面9090

報錯警告

原因:

主要是因為在啟動docker容器的時候或做docker配置的時候,還對防火墻設定重新啟動等配置,這樣會清除docker的相關配置,導致在查詢防火墻規則的時候顯示不到docker的鏈。iptables -L查詢iptables鏈。

解決:

是由於firewalld重新開機導致,而docker重新開機又會將其註冊iptables鏈找回來。

然後刪除剛才啟動失敗的容器,不然會繼續報錯容器已存在

systemctl restart docker #重新開機docker
docker ps -a #檢視執行容器
docker rm -f minio #根據容器名刪除容器(自己註意辨別自己的)

當啟動後在瀏覽器存取 http://localhost:9000 就可以存取minio的圖形化界面了,如圖所示:

使用者名稱密碼就是啟動參數裏面的數據

如果存取失敗,那就是防火墻問題或者是啟動參數最後兩項沒有添加,再不會有其他的,除非容器沒有啟動成功

檢視放行埠可以使用如下命令

 firewall-cmd --list-ports

要放行CentOS 7上的9000埠和9090埠,您可以按照以下步驟操作:

1.檢查防火墻狀態

使用以下命令檢查防火墻狀態:

systemctl status firewalld

如果防火墻已停止,則啟動它:

systemctl start firewalld

2.允許9000埠透過防火墻

使用以下命令允許TCP流量透過9000埠:

firewall-cmd --zone=public --add-port=9000/tcp --permanent
firewall-cmd --zone=public --add-port=9090/tcp --permanent

這將向防火墻添加一個規則,以允許TCP流量透過9000埠。要永久保存此更改,請執行以下命令:

firewall-cmd --reload

3.重新啟動防火墻服務shell

使用以下命令重新啟動防火墻服務:

systemctl restart firewalld

現在,您已經成功地放行了CentOS 7上的9000和9090埠。

五. 搭建springboot 環境

程式碼結構

引入計畫依賴

<!-- 操作minio的java客戶端-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.2</version>
</dependency>
<!-- 操作minio的java客戶端-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.1</version>
</dependency>
<!-- jwt鑒權相應依賴-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback- classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
</dependency>

建立容器桶

獲取API存取憑證

編寫配置檔

server:
port:8080
spring:
servlet:
multipart:
max-file-size:10MB
max-request-size:10MB
#minio配置
minio:
access-key:dAMaxkWaXUD1CV1JHbqw
secret-key:AXt3SD0JFkDENFbMeJKOOQb5wj8KvabZWu33Rs84
url:http://192.168.18.14:9090#存取地址
bucket-name:wanghui

首先是伺服器的配置:

埠號為8080,用於監聽請求。

使用了一個Servlet來處理 multipart/form-data 型別的請求。

在接收到 multipart/form-data 型別的請求時,會將上傳的檔大小限制在10MB以內,並將請求大小限制在10MB以內。

接下來是minio的配置:

access-key secret-key 是存取minio服務的憑證,需要根據實際情況進行填寫。

url是minio服務的地址,需要根據實際情況進行填寫。

bucket-name 是儲存檔的桶名,需要根據實際情況進行填寫。

http請求狀態

package com.xiaohui.utils;
/**
 * @Description http請求狀態
 * @Author IT小輝同學
 * @Date 2023/06/01
 */

public classHttpStatus
{
/**
* 操作成功
*/

publicstaticfinalint SUCCESS = 200;
/**
* 物件建立成功
*/

publicstaticfinalint CREATED = 201;
/**
* 請求已經被接受
*/

publicstaticfinalint ACCEPTED = 202;
/**
* 操作已經執行成功,但是沒有返回數據
*/

publicstaticfinalint NO_CONTENT = 204;
/**
* 資源已被移除
*/

publicstaticfinalint MOVED_PERM = 301;
/**
* 重新導向
*/

publicstaticfinalint SEE_OTHER = 303;
/**
* 資源沒有被修改
*/

publicstaticfinalint NOT_MODIFIED = 304;
/**
* 參數列錯誤(缺少,格式不匹配)
*/

publicstaticfinalint BAD_REQUEST = 400;
/**
* 未授權
*/

publicstaticfinalint UNAUTHORIZED = 401;
/**
* 存取受限,授權過期
*/

publicstaticfinalint FORBIDDEN = 403;
/**
* 資源,服務未找到
*/

publicstaticfinalint NOT_FOUND = 404;
/**
* 不允許的http方法
*/

publicstaticfinalint BAD_METHOD = 405;
/**
* 資源沖突,或者資源被鎖
*/

publicstaticfinalint CONFLICT = 409;
/**
* 不支持的數據,媒體型別
*/

publicstaticfinalint UNSUPPORTED_TYPE = 415;
/**
* 系統內部錯誤
*/

publicstaticfinalint ERROR = 500;
/**
* 介面未實作
*/

publicstaticfinalint NOT_IMPLEMENTED = 501;
/**
* 系統警告訊息
*/

publicstaticfinalint WARN = 601;
}















通用常量資訊

package com.xiaohui.utils;
import io.jsonwebtoken.Claims;
/**
 * @Description 通用常量資訊
 * @Author IT小輝同學
 * @Date 2023/06/01
 */

public classConstants
{
/**
* UTF-8 字元集
*/

publicstaticfinal String UTF8 = "UTF-8";
/**
* GBK 字元集
*/

publicstaticfinal String GBK = "GBK";
/**
* www主域
*/

publicstaticfinal String WWW = "www.";
/**
* http請求
*/

publicstaticfinal String HTTP = "http://";
/**
* https請求
*/

publicstaticfinal String HTTPS = "https://";
/**
* 通用成功標識
*/

publicstaticfinal String SUCCESS = "0";
/**
* 通用失敗標識
*/

publicstaticfinal String FAIL = "1";
/**
* 登入成功
*/

publicstaticfinal String LOGIN_SUCCESS = "Success";
/**
* 登出
*/

publicstaticfinal String LOGOUT = "Logout";
/**
* 註冊
*/

publicstaticfinal String REGISTER = "Register";
/**
* 登入失敗
*/

publicstaticfinal String LOGIN_FAIL = "Error";
/**
* 驗證碼有效期(分鐘)
*/

publicstaticfinal Integer CAPTCHA_EXPIRATION = 2;
/**
* 令牌
*/

publicstaticfinal String TOKEN = "token";
/**
* 令牌字首
*/

publicstaticfinal String TOKEN_PREFIX = "Bearer ";
/**
* 令牌字首
*/

publicstaticfinal String LOGIN_USER_KEY = "login_user_key";
/**
* 使用者ID
*/

publicstaticfinal String JWT_USERID = "userid";
/**
* 使用者名稱稱
*/

publicstaticfinal String JWT_USERNAME = Claims.SUBJECT;
/**
* 使用者頭像
*/

publicstaticfinal String JWT_AVATAR = "avatar";
/**
* 建立時間
*/

publicstaticfinal String JWT_CREATED = "created";
/**
* 使用者許可權
*/

publicstaticfinal String JWT_AUTHORITIES = "authorities";
/**
* 資源對映路徑 字首
*/

publicstaticfinal String RESOURCE_PREFIX = "/profile";
/**
* RMI 遠端方法呼叫
*/

publicstaticfinal String LOOKUP_RMI = "rmi:";
/**
* LDAP 遠端方法呼叫
*/

publicstaticfinal String LOOKUP_LDAP = "ldap:";
/**
* LDAPS 遠端方法呼叫
*/

publicstaticfinal String LOOKUP_LDAPS = "ldaps:";
/**
* 定時任務白名單配置(僅允許存取的包名,如其他需要可以自行添加)
*/

publicstaticfinal String[] JOB_WHITELIST_STR = { "com.ruoyi" };
/**
* 定時任務違規的字元
*/

publicstaticfinal String[] JOB_ERROR_STR = { "java.net.URL""javax.naming.InitialContext""org.yaml.snakeyaml",
"org.springframework""org.apache""com.ruoyi.common.utils.file""com.ruoyi.common.config" };
}

























建立Minio的配置類

package com.xiaohui.config;
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @Description minio配置
 * @Author IT小輝同學
 * @Date 2023/06/02
 */

@Data
@Configuration
@ConfigurationProperties(prefix = "spring.minio")
public classMinioConfig{
private String accessKey;
private String secretKey;
private String url;
private String bucketName;
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint(url)
.credentials(accessKey,secretKey)
.build();
}
}




這段程式碼是Java中的一個配置類,用於配置與MinIO(一個物件儲存服務)相關的內容。具體來說:

@Configuration 註解表示這是一個配置類,用於將該類中定義的內容註入到其他元件中使用。

@ConfigurationProperties 註解表示該類使用了 spring.minio.* 字首的內容來配置Minio相關的內容。

@Data 註解表示自動生成getter和setter方法,簡化了程式碼編寫。

accessKey secretKey 內容分別表示存取金鑰和金鑰值,用於連線到MinIO服務。

url內容表示MinIO服務的URL地址。

bucketName 內容表示儲存桶名稱。

@Bean 註解表示將 minioClient() 方法返回的物件註冊為bean,以便在其他元件中使用。

minioClient() 方法返回了一個 MinioClient 物件,用於連線到MinIO服務並操作儲存桶。其中, endpoint() 方法用於設定MinIO服務的URL地址, credentials() 方法用於設定存取金鑰和金鑰值。

建立Minio的工具類

package com.xiaohui.utils;

import com.xiaohui.config.MinioConfig;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.SneakyThrows;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
 * @Description Minio工具類
 * @Author IT小輝同學
 * @Date 2023/06/02
 */

@Component
public classMinioUtils{
@Autowired
private MinioClient minioClient;
@Autowired
private MinioConfig configuration;
/**
@param name 名字
@return boolean
@Description description: 判斷bucket是否存在,不存在則建立
@Author IT小輝同學
@Date 2023/06/02
*/

publicbooleanexistBucket(String name){
boolean exists;
try {
exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build());
if (!exists) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build());
exists = true;
}
catch (Exception e) {
e.printStackTrace();
exists = false;
}
return exists;
}
/**
@param bucketName 儲存bucket名稱
@return {@link Boolean }
@Description 建立儲存bucket
@Author IT小輝同學
@Date 2023/06/02
*/

public Boolean makeBucket(String bucketName){
try {
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(bucketName)
.build());
catch (Exception e) {
e.printStackTrace();
returnfalse;
}
returntrue;
}
/**
@param bucketName 儲存bucket名稱
@return {@link Boolean }
@Description 刪除儲存bucket
@Author IT小輝同學
@Date 2023/06/02
*/

public Boolean removeBucket(String bucketName){
try {
minioClient.removeBucket(RemoveBucketArgs.builder()
.bucket(bucketName)
.build());
catch (Exception e) {
e.printStackTrace();
returnfalse;
}
returntrue;
}
/**
@param fileName 檔名稱
@param time 時間
@return {@link Map }
@Description 獲取上傳臨時簽名
@Author IT小輝同學
@Date 2023/06/02
*/

@SneakyThrows
public Map getPolicy(String fileName, ZonedDateTime time){
PostPolicy postPolicy = new PostPolicy(configuration.getBucketName(), time);
postPolicy.addEqualsCondition("key", fileName);
try {
Map<String, String> map = minioClient.getPresignedPostFormData(postPolicy);
HashMap<String, String> map1 = new HashMap<>();
map.forEach((k, v) -> {
map1.put(k.replaceAll("-"""), v);
});
map1.put("host", configuration.getUrl() + "/" + configuration.getBucketName());
return map1;
catch (ErrorResponseException e) {
e.printStackTrace();
catch (InsufficientDataException e) {
e.printStackTrace();
catch (InternalException e) {
e.printStackTrace();
catch (InvalidKeyException e) {
e.printStackTrace();
catch (InvalidResponseException e) {
e.printStackTrace();
catch (IOException e) {
e.printStackTrace();
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
catch (ServerException e) {
e.printStackTrace();
catch (XmlParserException e) {
e.printStackTrace();
}
returnnull;
}
/**
@param objectName 物件名稱
@param method 方法
@param time 時間
@param timeUnit 時間單位
@return {@link String }
@Description 獲取上傳檔的url
@Author IT小輝同學
@Date 2023/06/02
*/

public String getPolicyUrl(String objectName, Method method, int time, TimeUnit timeUnit){
try {
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(method)
.bucket(configuration.getBucketName())
.object(objectName)
.expiry(time, timeUnit).build());
catch (ErrorResponseException e) {
e.printStackTrace();
catch (InsufficientDataException e) {
e.printStackTrace();
catch (InternalException e) {
e.printStackTrace();
catch (InvalidKeyException e) {
e.printStackTrace();
catch (InvalidResponseException e) {
e.printStackTrace();
catch (IOException e) {
e.printStackTrace();
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
catch (XmlParserException e) {
e.printStackTrace();
catch (ServerException e) {
e.printStackTrace();
}
returnnull;
}

/**
@param file 檔
@param fileName 檔名稱
@Description 上傳檔
@Author IT小輝同學
@Date 2023/06/02
*/

publicvoidupload(MultipartFile file, String fileName){
// 使用putObject上傳一個檔到儲存桶中。
try {
InputStream inputStream = file.getInputStream();
minioClient.putObject(PutObjectArgs.builder()
.bucket(configuration.getBucketName())
.object(fileName)
.stream(inputStream, file.getSize(), -1)
.contentType(file.getContentType())
.build());
catch (ErrorResponseException e) {
e.printStackTrace();
catch (InsufficientDataException e) {
e.printStackTrace();
catch (InternalException e) {
e.printStackTrace();
catch (InvalidKeyException e) {
e.printStackTrace();
catch (InvalidResponseException e) {
e.printStackTrace();
catch (IOException e) {
e.printStackTrace();
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
catch (ServerException e) {
e.printStackTrace();
catch (XmlParserException e) {
e.printStackTrace();
}
}
/**
@param objectName 物件名稱
@param time 時間
@param timeUnit 時間單位
@return {@link String }
@Description 根據filename獲取檔存取地址
@Author IT小輝同學
@Date 2023/06/02
*/

public String getUrl(String objectName, int time, TimeUnit timeUnit){
String url = null;
try {
url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(configuration.getBucketName())
.object(objectName)
.expiry(time, timeUnit).build());
catch (ErrorResponseException e) {
e.printStackTrace();
catch (InsufficientDataException e) {
e.printStackTrace();
catch (InternalException e) {
e.printStackTrace();
catch (InvalidKeyException e) {
e.printStackTrace();
catch (InvalidResponseException e) {
e.printStackTrace();
catch (IOException e) {
e.printStackTrace();
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
catch (XmlParserException e) {
e.printStackTrace();
catch (ServerException e) {
e.printStackTrace();
}
return url;
}
/**
@param fileName
@return {@link ResponseEntity }<{@link byte[] }>
@Description description: 下載檔
@Author IT小輝同學
@Date 2023/06/02
*/

public ResponseEntity<byte[]> download(String fileName) {
ResponseEntity<byte[]> responseEntity = null;
InputStream in = null;
ByteArrayOutputStream out = null;
try {
in = minioClient.getObject(GetObjectArgs.builder().bucket(configuration.getBucketName()).object(fileName).build());
out = new ByteArrayOutputStream();
IOUtils.copy(in, out);
//封裝返回值
byte[] bytes = out.toByteArray();
HttpHeaders headers = new HttpHeaders();
try {
headers.add("Content-Disposition""attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
headers.setContentLength(bytes.length);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setAccessControlExposeHeaders(Arrays.asList("*"));
responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.SUCCESS);
catch (Exception e) {
e.printStackTrace();
finally {
try {
if (in != null) {
try {
in.close();
catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
return responseEntity;
}
/**
@param objectFile 物件檔
@return {@link String }
@Description 根據檔名和桶獲取檔路徑
@Author IT小輝同學
@Date 2023/06/02
*/

public String getFileUrl(String objectFile){
try {
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(configuration.getBucketName())
.object(objectFile)
.build()
);
catch (Exception e) {
e.printStackTrace();
}
returnnull;
}

}
















該程式碼是一個工具類,用於使用阿裏雲的物件儲存服務(OSS)進行檔上傳和下載。具體功能如下:

getPolicy(String fileName, ZonedDateTime time) :根據檔名和時間戳獲取上傳臨時簽名。

getPolicyUrl(String objectName, Method method, int time, TimeUnit timeUnit) :獲取上傳檔的url。

upload(MultipartFile file, String fileName) :將檔上傳到OSS中。

getUrl(String objectName, int time, TimeUnit timeUnit) :獲取檔的下載url。

程式碼中使用了列舉型別來定義不同的上傳和下載方法。

使用了註解 @Autowired 來自動註入 MinioClient 物件。

該工具類沒有提供例外處理機制,需要根據實際情況進行補充。

建立Ajax請求工具類


/**
 * @Description ajax結果
 * @Author IT小輝同學
 * @Date 2023/06/01
 */

public classAjaxResultextendsHashMap<StringObject>
{
privatestaticfinallong serialVersionUID = 1L;
/** 狀態碼 */
publicstaticfinal String CODE_TAG = "code";
/** 返回內容 */
publicstaticfinal String MSG_TAG = "msg";
/** 數據物件 */
publicstaticfinal String DATA_TAG = "data";
/**
* 初始化一個新建立的 AjaxResult 物件,使其表示一個空訊息。
*/

publicAjaxResult()
{
}
/**
* 初始化一個新建立的 AjaxResult 物件
*
@param code 狀態碼
@param msg 返回內容
*/

publicAjaxResult(int code, String msg)
{
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
}
/**
* 初始化一個新建立的 AjaxResult 物件
*
@param code 狀態碼
@param msg 返回內容
@param data 數據物件
*/

publicAjaxResult(int code, String msg, Object data)
{
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
if (data!=null)
{
super.put(DATA_TAG, data);
}
}
/**
* 返回成功訊息
*
@return 成功訊息
*/

publicstatic AjaxResult success()
{
return AjaxResult.success("操作成功");
}
/**
* 返回成功數據
*
@return 成功訊息
*/

publicstatic AjaxResult success(Object data)
{
return AjaxResult.success("操作成功", data);
}
/**
* 返回成功訊息
*
@param msg 返回內容
@return 成功訊息
*/

publicstatic AjaxResult success(String msg)
{
return AjaxResult.success(msg, null);
}
/**
* 返回成功訊息
*
@param msg 返回內容
@param data 數據物件
@return 成功訊息
*/

publicstatic AjaxResult success(String msg, Object data)
{
returnnew AjaxResult(HttpStatus.SUCCESS, msg, data);
}
/**
* 返回警告訊息
*
@param msg 返回內容
@return 警告訊息
*/

publicstatic AjaxResult warn(String msg)
{
return AjaxResult.warn(msg, null);
}
/**
* 返回警告訊息
*
@param msg 返回內容
@param data 數據物件
@return 警告訊息
*/

publicstatic AjaxResult warn(String msg, Object data)
{
returnnew AjaxResult(HttpStatus.WARN, msg, data);
}
/**
* 返回錯誤訊息
*
@return 錯誤訊息
*/

publicstatic AjaxResult error()
{
return AjaxResult.error("操作失敗");
}
/**
* 返回錯誤訊息
*
@param msg 返回內容
@return 錯誤訊息
*/

publicstatic AjaxResult error(String msg)
{
return AjaxResult.error(msg, null);
}
/**
* 返回錯誤訊息
*
@param msg 返回內容
@param data 數據物件
@return 錯誤訊息
*/

publicstatic AjaxResult error(String msg, Object data)
{
returnnew AjaxResult(HttpStatus.ERROR, msg, data);
}
/**
* 返回錯誤訊息
*
@param code 狀態碼
@param msg 返回內容
@return 錯誤訊息
*/

publicstatic AjaxResult error(int code, String msg)
{
returnnew AjaxResult(code, msg, null);
}
/**
* 方便鏈式呼叫
*
@param key 鍵
@param value 值
@return 數據物件
*/

@Override
public AjaxResult put(String key, Object value)
{
super.put(key, value);
returnthis;
}
}















建立Minio檔操作介面層

package com.xiaohui.controller;
import com.xiaohui.utils.AjaxResult;
import com.xiaohui.utils.MinioUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
/**
 * @Description minio檔上傳控制器
 * @Author IT小輝同學
 * @Date 2023/06/02
 */

@CrossOrigin
@RestController
@RequestMapping("/api")
public classMinioFileUploadController{
@Autowired
private MinioUtils minioUtils;
/**
@param file 檔
@param fileName 檔名稱
@return {@link AjaxResult }
@Description 上傳檔
@Author IT小輝同學
@Date 2023/06/02
*/

@GetMapping("/upload")
public AjaxResult uploadFile(@RequestParam("file") MultipartFile file, String fileName) {
minioUtils.upload(file, fileName);
return AjaxResult.success("上傳成功");
}
/**
@param fileName 檔名稱
@return {@link ResponseEntity }
@Description dowload檔
@Author IT小輝同學
@Date 2023/06/02
*/

@GetMapping("/dowload")
public ResponseEntity dowloadFile(@RequestParam("fileName") String fileName) {
return minioUtils.download(fileName);
}
/**
@param fileName 檔名稱
@return {@link AjaxResult }
@Description 得到檔url
@Author IT小輝同學
@Date 2023/06/02
*/

@GetMapping("/getUrl")
public AjaxResult getFileUrl(@RequestParam("fileName") String fileName){
HashMap map=new HashMap();
map.put("FileUrl",minioUtils.getFileUrl(fileName));
return AjaxResult.success(map);
}
}






六. 功能測試

Minio大檔上傳

Minio大檔地址

來源:juejin.cn/post/7304539173972983860

🔥 磊哥私藏精品 熱門推薦 🔥