minio高可用 架構與實操(圖解+秒懂+史上最全)


文章很長,而且持續更新,建議收藏起來,慢慢讀!瘋狂創客圈總目錄 博客園版 為您奉上珍貴的學習資源 :

免費贈送 :《尼恩Java面試寶典》 持續更新+ 史上最全 + 面試必備 2000頁+ 面試必備 + 大廠必備 +漲薪必備
免費贈送 經典圖書:《Java高並發核心編程(卷1)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:《Java高並發核心編程(卷2)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:《Java高並發核心編程(卷3)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:尼恩Java面試寶典 最新版 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 資源寶庫: Java 必備 百度網盤資源大合集 價值>10000元 加尼恩領取


背景:

下一個視頻版本,從架構師視角,尼恩為大家打造高可用、高並發中間件的原理與實操。

目標:通過視頻和博客的方式,為各位潛力架構師,徹底介紹清楚架構師必須掌握的高可用、高並發環境,包括但不限於:

  • 高可用、高並發nginx架構的原理與實操

  • 高可用、高並發mysql架構的原理與實操

  • 高可用、高並發nacos架構的原理與實操

  • 高可用、高並發rocketmq架構的原理與實操

  • 高可用、高並發es架構的原理與實操

  • 高可用、高並發minio架構的原理與實操

在這里插入圖片描述

why 高可用、高並發中間件的原理與實操:

  • 實際的開發過程中,很多小伙伴聚焦crud開發,環境出了問題,都不能啟動。

  • 作為架構師,或者未來想走向高端開發,或者做架構,必須掌握高可用、高並發中間件的原理,掌握其實操。

本系列博客的具體內容,請參見 Java 高並發 發燒友社群:瘋狂創客圈

分布式文件系統應用場景

​ 互聯網下海量的非結構化存儲的需求背景下,比如:

  • 電商網站,存儲海量的商品圖片
  • 視頻網站,海量的視頻文件
  • 網盤,海量的文件
  • 社交網站等等

​ 在這樣的背景下,傳統的FastDFS部署太過於繁瑣,動不動就是來個nginx,然后配置一堆參數和設置,尤其是做分布式的時候,那維護成本一下就上來了,從維護和部署的角度,FastDFS不是一個好的選擇,而從迭代的角度,FastDFS早就不維護了,有很多需求是無法

支持到的,那么就需要你自己思考寫源碼打包了。

同理HDFS部署也不簡單,而且Hadoop適合超大文件的存儲,並且文件都需要分片,應用場景更多是計算處理,實時數據分析,並且其實HDFS比較吃硬件設備,因為偏於計算,所以對CPU的要求比較高,對於中小企業的業務量並沒有這么大,所以應用場景這塊也比較

難接觸到,但是HDFS的功能還是十分強大的!!還是根據業務進行選型。

說明:本文會以pdf格式持續更新,更多最新尼恩3高pdf筆記,請從下面的鏈接獲取:語雀 或者 碼雲

存儲方案的選型

以下選型方案,來自於探探

這是探探app的幾個功能,它的基礎功能非常簡單左划右划,左划是不喜歡,右划是喜歡,當兩個人相互喜歡就配對成功了,配對成功之后就開始相互聊天。

在這里插入圖片描述

你所看到的一些圖片、視頻還有在聊天中產生的語音,這些元素在對象存儲的范疇里面,就是以對象保存下來。

隨着用戶量的增長,探探所要存儲的對象越來越多。

探探存儲的文件類型

在這里插入圖片描述

這是探探2019年的文件存儲數據.

  • 數據的體量為:

在不同類型對象所占的空間中,顯而易見圖片是存儲的一個大頭,超過了 1PB,它定期清理所以大小基本上保持了穩定的狀態。

  • 訪問的吞吐量數據為:

寫入的 QPS 大概是 1 千左右,讀取是 5 千左右,壓力不是很大。

方案選型

在這里插入圖片描述

於是,探探團隊就開始調研當前的一些開源方案,這些存儲方案里面可以分為兩種:

  • 一種是可以自定對象名稱的;

  • 另外一種是系統自動生成對象名稱。

探探的對象名是自己生成的,里面包含了業務邏輯。

像 FS 就是國內大佬開源的一個分支存儲,但是因為不能自定義文件名所以不合適,左划掉。

還有像領英的 Ambry、MogileFS 其實都不能自定對象名的,所以是不合適的。

左上角 LeoFS 對探探來說不是很可控,所以不合適。

TFS 是淘寶開源的,但是目前已經很少有人維護它並且也不是很活躍,所以當時就沒有考慮。

ceph 是一個比較強大的分布式存儲,但是它整個系統非常復雜需要大量的人力進行維護,和探探的產品不是很符合,所以暫時不考慮。

GlusterFS 為本身是一個非常成熟的對象存儲的方案。2011年左右被收購了,他們原版人馬又做了另外一個存儲系統MINIO,仙鶴就是他們的 logo。

MINIO 的文檔非常詳細、具體,再加上他們之前在存儲方面有十幾年的經驗,所以就這樣打動了探探團隊,作為選型的標的。

MinIO 介紹

Minio 是個基於 Golang 編寫的開源對象存儲套件,雖然輕量,卻擁有着不錯的性能。

官網地址:MinIO | High Performance, Kubernetes Native Object Storage

何為對象存儲?

對象存儲服務(Object Storage Service,OSS)是一種海量、安全、低成本、高可靠的雲存儲服務,適合存放任意類型的文件。容量和處理能力彈性擴展,多種存儲類型供選擇,全面優化存儲成本。

MinIO 是一個基於Apache License v2.0開源協議的對象存儲服務。

它兼容亞馬遜S3雲存儲服務接口,非常適合於存儲大容量非結構化的數據,例如圖片、視頻、日志文件、備份數據和容器/虛擬機鏡像等,而一個對象文件可以是任意大小,從幾kb到最大5T不等。

MinIO是一個非常輕量的服務,可以很簡單的和其他應用的結合,類似 NodeJS, Redis 或者 MySQL。

對於中小型企業,如果不選擇存儲上雲,那么 Minio 是個不錯的選擇,麻雀雖小,五臟俱全。

當然 Minio 除了直接作為對象存儲使用,還可以作為雲上對象存儲服務的網關層,無縫對接到 Amazon S3、MicroSoft Azure。

說明:本文會以pdf格式持續更新,更多最新尼恩3高pdf筆記,請從下面的鏈接獲取:語雀 或者 碼雲

MINIO 基礎概念

MINIO 有幾個概念比較重要:

  • Object:存儲到 Minio 的基本對象,如文件、字節流,Anything...

  • Bucket:用來存儲 Object 的邏輯空間。每個 Bucket 之間的數據是相互隔離的。對於客戶端而言,就相當於一個存放文件的頂層文件夾。

  • Drive:即存儲數據的磁盤,在 MinIO 啟動時,以參數的方式傳入。Minio 中所有的對象數據都會存儲在 Drive 里。

  • Set

    即一組 Drive 的集合,分布式部署根據集群規模自動划分一個或多個 Set ,每個 Set 中的 Drive 分布在不同位置。一個對象存儲在一個 Set 上。(For example: {1...64} is divided into 4 sets each of size 16.)

    • 一個對象存儲在一個Set上
    • 一個集群划分為多個Set
    • 一個Set包含的Drive數量是固定的,默認由系統根據集群規模自動計算得出
    • 一個SET中的Drive盡可能分布在不同的節點上

Set /Drive 的關系

Set /Drive 這兩個概念是 MINIO 里面最重要的兩個概念,一個對象最終是存儲在 Set 上面的。

我們來看下邊 MINIO 集群存儲示意圖,每一行是一個節點機器,這有 32 個節點,每個節點里有一個小方塊我們稱之 Drive,Drive 可以簡單地理解為一個硬盤。

圖中,一個節點有 32 個 Drive,相當於 32 塊硬盤。

Set 是另外一個概念,Set 是一組 Drive 的集合,圖中,所有藍色、橙色背景的Drive(硬盤)的就組成了一個 Set.

在這里插入圖片描述

MIINO如何寫入對象?

MINIO 是通過數據編碼,將原來的數據編碼成 N 份,N 就是一個 Set 上面 Drive 的數量,后面多次提到的 N 都是指這個意思。

上圖中,一個 Set 上面 Drive 的數量,是3.

對象被編碼成N份之后,把每一份,寫到對應的 Drive 上面,這就是把一個對象存儲在整個 Set 上。

在這里插入圖片描述

一個集群包含多個 Set,每個對象最終存儲在哪個 Set 上是根據對象的名稱進行哈希,然后影射到唯一的 Set 上面,這個方式從理論上保證數據可以均勻的分布到所有的 Set 上。

根據的觀測,數據分布的也非常均勻,一個 Set 上包含多少個 Drive 是由系統自動根據集群規模算出來的,當然,也可以自己去配置。

一個 Set 的 Drive 系統會考慮盡可能把它放在多的節點上面,保證它的可靠性。

Minio存儲架構

Minio針對不同應用場景也設置了對應的存儲架構:

單主機,單硬盤模式

img

該模式下,Minio只在一台服務器上搭建服務,且數據都存在單塊磁盤上,該模式存在單點風險,主要用作開發、測試等使用

啟動的命令為:

minio --config-dir ~/tenant1 server --address :9001 /disk1/data/tenant1

單主機,多硬盤模式

img

該模式下,Minio在一台服務器上搭建服務,但數據分散在多塊(大於4塊)磁盤上,提供了數據上的安全保障

minio --config-dir ~/tenant1 server --address :9001 /disk1/data/tenant1 /disk2/data/tenant1 /disk3/data/tenant1 /disk4/data/enant1

多主機、多硬盤模式(分布式)

img

該模式是Minio服務最常用的架構,通過共享一個access_key和secret_key,在多台(2-32)服務器上搭建服務,且數據分散在多塊(大於4塊,無上限)磁盤上,提供了較為強大的數據冗余機制(Reed-Solomon糾刪碼)。

export MINIO_ACCESS_KEY=<TENANT1_ACCESS_KEY>
export MINIO_SECRET_KEY=<TENANT1_SECRET_KEY>
minio --config-dir ~/tenant1 server --address :9001 http://192.168.10.11/data/tenant1 http://192.168.10.12/data/tenant1 http://192.168.10.13/data/tenant1 http://192.168.10.14/data/tenant1

說明:本文會以pdf格式持續更新,更多最新尼恩3高pdf筆記,請從下面的鏈接獲取:語雀 或者 碼雲

分布式Minio有什么好處?

在大數據領域,通常的設計理念都是無中心和分布式。Minio分布式模式可以幫助你搭建一個高可用的對象存儲服務,你可以使用這些存儲設備,而不用考慮其真實物理位置。

數據保護

分布式Minio采用 糾刪碼來防范多個節點宕機和位衰減bit rot

分布式Minio至少需要4個硬盤,使用分布式Minio自動引入了糾刪碼功能。

高可用

單機Minio服務存在單點故障,相反,如果是一個有N塊硬盤的分布式Minio, 只要有N/2硬盤在線,你的數據就是安全的。

不過你需要至少有N/2+1個硬盤來創建新的對象。

例如,一個16節點的Minio集群,每個節點16塊硬盤,就算8台服務器宕機,這個集群仍然是可讀的,不過你需要9台服務器才能寫數據。

注意,只要遵守分布式Minio的限制,你可以組合不同的節點和每個節點幾塊硬盤。

比如,你可以使用2個節點,每個節點4塊硬盤,也可以使用4個節點,每個節點兩塊硬盤,諸如此類。

一致性

Minio在分布式和單機模式下,所有讀寫操作都嚴格遵守read-after-write一致性模型。

MinIO的數據高可靠

Minio使用了Erasure Code 糾刪碼Bit Rot Protection 數據腐化保護這兩個特性,所以MinIO的數據可靠性做的高。

Erasure Code糾刪碼

糾刪碼(Erasure Code)簡稱EC,是一種數據保護方法,它將數據分割成片段,把冗余數據塊擴展、編碼,並將其存儲在不同的位置,比如磁盤、存儲節點或者其它地理位置。

從數據函數角度來說,糾刪碼提供的保護可以用下面這個簡單的公式來表示:n = k + m。變量“k”代表原始數據或符號的值。變量“m”代表故障后添加的提供保護的額外或冗余符號的值。變量“n”代表糾刪碼過程后創建的符號的總值。

舉個例子,假設n=16,代表有16塊磁盤,另外,有10份原始文件一模一樣,稱為k,16 = 10 +m,這個m就是可以恢復的校驗塊個數,所以m是6,任意6個不可用,原始文件都可以恢復,極端情況,10個原始文件壞掉6個,靠4個原始的加上6個校驗塊,可以把壞掉的6個原始文件恢復,這個用到數學行列式矩陣知識,不做展開。

MinIO的編碼方式,將一個對象編碼成若干個數據塊和校驗塊,我們簡稱為Erasure Code碼,這個是編碼的類型,這種編碼的類型,還需要算法來實現,minio 采用的是 Reed-Solomon算法。

MinIO使用Reed-Solomon算法,該算法把對象編碼成若干個數據塊和校驗塊。

Reed-Solomon算法的特點:

  • 低冗余
  • 高可靠

為了表述方便,把數據塊和校驗塊統稱為編碼塊,之后我們可以通過編碼塊的一部分就能還原出整個對象。

Reed-Solomon code

Reed-Solomon 是糾刪碼的實現算法的一種,當然,也是一種恢復丟失和損壞數據的數學算法,

Minio默認采用Reed-Solomon code將數據拆分成N/2個數據塊和N/2個奇偶校驗塊。

這就意味着如果是16塊盤,一個對象會被分成8個數據塊、8個奇偶校驗塊,你可以丟失任意8塊盤(不管其是存放的數據塊還是校驗塊),你仍可以從剩下的盤中的數據進行恢復。

img

如上圖,如我們所知,一個對象存儲在一個Set上面,這個Set包含16個Drive,其中灰色的一半是數據庫,橙色的一半是校驗塊,這種方式最多能忍受一半的編碼丟失或損壞。

所有編碼塊的大小是原對象的2倍,跟傳統多副本存儲方案相比,他只冗余存了一份,但可靠性更高。

糾刪碼的工作原理和RAID或者副本不同,像RAID6只能在損失兩塊盤,或者以下的情況下不丟數據,而Minio糾刪碼可以在丟失一半的盤的情況下,仍可以保證數據安全。

而且Minio糾刪碼是作用在對象級別,可以一次恢復一個對象,而RAID是作用在卷級別,數據恢復時間很長。

Minio對每個對象單獨編碼,存儲服務一經部署,通常情況下是不需要更換硬盤或者修復。

此外,針對不同應用所需的數據安全級別不同,Minio還提供了存儲級別(Storage Class)的配置,調整數據塊和校驗塊的比例,做到對空間的最佳使用。

img

比如在將比例調整為14:2后,存儲100M的數據占用的空間僅為114M。

Bit Rot Protection:

接下來講Bit Rot Protection,直譯就是腐爛。

它只是物理設備上的一些文件細微的損壞,還沒有被操作系統所硬件所察覺,但是他已經損壞了。

Bit Rot 位衰減又被稱為數據腐化Data Rot無聲數據損壞Silent Data Corruption,

位衰減可以理解為無形中的數據丟失——或者稱為“Bit rot”, 是指物理存儲介質的衰減所帶來的隱患將凸顯出來。

位衰減是目前硬盤數據的一種嚴重數據丟失問題。

硬盤上的數據可能會神不知鬼不覺就損壞了,也沒有什么錯誤日志。

一項對150萬塊硬盤的研究表明,每90塊硬盤就有1塊有這種“軟錯誤”,這個錯誤不但會導致數據丟失,還會導致RAID錯誤。

針對這一問題,最新的Minio采用了HighwayHash算法計算校驗和來防范位衰減,根據測試結果,其可以實現10GB/s的處理速度。

大致的做法是:

MinIO把之前的編碼塊進行 HighwayHash 編碼,最后要校驗這個編碼,以確保每個編碼是正確的。

文件的修復

另外,MinIO提供了一個管理工具,可以對所有編碼塊進行校驗,如果發現編碼塊有問題,再去修復它。

得益於Reed-Solomon糾刪碼,Minio可以更加靈活的對文件進行修復。

目前,Minio提供了全量、bucket、文件夾、文件等各個粒度的修復操作:

遞歸修復


$ mc admin heal -r myminio

指定桶修復

$ mc admin heal -r myminio/dev

下面是幾個例子:

img

img

img

img

相比一般的RAID方式,Minio可以在非常小的粒度下對文件進行修復操作,靈活性有了很大提高。

修復后,可以JSON格式列出指定路徑(文件、大小)


$ mc ls -r --json myminio/dev

{
 "status": "success",
 "type": "file",
 "lastModified": "2019-05-30T09:43:07.763-04:00",
 "size": 44996289,
 "key": "myFile",
 "etag": "bae58dc18zzzzz54c14e233b520e0a"
}

說明:本文會以pdf格式持續更新,更多最新尼恩3高pdf筆記,請從下面的鏈接獲取:語雀 或者 碼雲

部署實操

Minio 提供了兩種部署方式:

  • 單機部署
  • 分布式

兩種部署方式都非常簡單,其中分布式部署還提供了糾刪碼功能來降低數據丟失的風險。

單機部署:

minio server /data

分布式部署:

export MINIO_ACCESS_KEY=<ACCESS_KEY>
export MINIO_SECRET_KEY=<SECRET_KEY>
minio server http://host{1...n}/export{1...m} http://host{1...o}/export{1...m}

Docker Compose部署

官方的文檔:

https://docs.min.io/cn/deploy-minio-on-docker-compose.html

Docker Compose允許定義和運行單主機,多容器Docker應用程序。

使用Compose,您可以使用Compose文件來配置MinIO服務。 然后,使用單個命令,您可以通過你的配置創建並啟動所有分布式MinIO實例。 分布式MinIO實例將部署在同一主機上的多個容器中。 這是建立基於分布式MinIO的開發,測試和分期環境的好方法。

環境說明

操作系統 ip地址 docker版本 Docker Compose版本
centos 7.6 192.168.31.34 19.03.8 1.24.1

運行分布式MinIO

在Docker Compose上部署分布式MinIO,請下載docker-compose.yaml到你的當前工作目錄。Docker Compose會pull MinIO Docker Image,所以你不需要手動去下載MinIO binary。然后運行下面的命令

docker-compose pull
docker-compose up -d

現在每個實例都可以訪問,端口從9001到9004,請在瀏覽器中訪問http://127.0.0.1:9001/

注意事項

  • 默認情況下Docker Compose file使用的是最新版的MinIO server的Docker鏡像,你可以修改image tag來拉取指定版本的MinIO Docker image.

  • 默認情況下會創建4個minio實例,你可以添加更多的MinIO服務(最多總共16個)到你的MinIO Comose deployment。添加一個服務

    • 復制服務定義並適當地更改新服務的名稱。
    • 更新每個服務中的命令部分。
    • 更新要為新服務公開的端口號。 另外,請確保分配給新服務的端口尚未使用。

    關於分布式MinIO的更多資料,請訪問這里.

  • Docker compose file中的MinIO服務使用的端口是9001到9004,這允許多個服務在主機上運行。

訪問MinIO

http://192.168.31.34:9001/minio/

用戶名:minio,密碼:minio123

img

登錄之后,效果如下:

img

MinIO操作

修改密碼

點擊右上角

img

提示:無法通過瀏覽器更新此用戶的憑據

img

注意:如果需要修改密碼,修改docker-compose.yaml中的MINIO_ACCESS_KEY和MINIO_SECRET_KEY變量即可。

創建bucket(文件夾)

先來創建一個bucket

img

創建data

img

上傳文件

選中data,點擊右下角的上傳文件

img

選擇一張圖片,上傳成功之后,效果如下:

img

查看bucket文件信息

點擊data,查看與設置該Object的基本信息:
查看共享地址Shareable Link

img

設置到期時間,最大可保存時間為7天

對話框上方彈出該Object現剩余到期時間

img

說明:本文會以pdf格式持續更新,更多最新尼恩3高pdf筆記,請從下面的鏈接獲取:語雀 或者 碼雲

附錄1:Minio糾刪碼的補充學習

Minio使用糾刪碼erasure code和校驗和checksum來保護數據免受硬件故障和無聲數據損壞。 即便您丟失一半數量(N/2)的硬盤,您仍然可以恢復數據。

什么是糾刪碼erasure code?

糾刪碼是一種恢復丟失和損壞數據的數學算法, Minio采用Reed-Solomon code 算法將對象拆分成N/2數據和N/2 奇偶校驗塊。 這就意味着如果是12塊盤,一個對象會被分成6個數據塊、6個奇偶校驗塊,你可以丟失任意6塊盤(不管其是存放的數據塊還是奇偶校驗塊),你仍可以從剩下的盤中的數據進行恢復,是不是很NB,感興趣的同學請FQgoogle。

為什么糾刪碼有用?

糾刪碼的工作原理和RAID或者復制不同,像RAID6可以在損失兩塊盤的情況下不丟數據,而Minio糾刪碼可以在丟失一半的盤的情況下,仍可以保證數據安全。 而且Minio糾刪碼是作用在對象級別,可以一次恢復一個對象,而RAID是作用在卷級別,數據恢復時間很長。 Minio對每個對象單獨編碼,存儲服務一經部署,通常情況下是不需要更換硬盤或者修復。Minio糾刪碼的設計目標是為了性能和盡可能的使用硬件加速。

Erasure

Minio糾刪碼實驗

1. 前提條件:

安裝Minio- Minio快速入門

2. 以糾刪碼模式運行Minio

示例: 使用Minio,在12個盤中啟動Minio服務。

minio server /data1 /data2 /data3 /data4 /data5 /data6 /data7 /data8 /data9 /data10 /data11 /data12

示例: 使用Minio Docker鏡像,在8塊盤中啟動Minio服務。

docker run -p 9000:9000 --name minio \
  -v /mnt/data1:/data1 \
  -v /mnt/data2:/data2 \
  -v /mnt/data3:/data3 \
  -v /mnt/data4:/data4 \
  -v /mnt/data5:/data5 \
  -v /mnt/data6:/data6 \
  -v /mnt/data7:/data7 \
  -v /mnt/data8:/data8 \
  minio/minio server /data1 /data2 /data3 /data4 /data5 /data6 /data7 /data8

3. 驗證是否設置成功

你可以隨意拔掉硬盤,看Minio是否可以正常讀寫。

附錄2:什么是位衰減bit rot保護?

位衰減又被稱為數據腐化Data Rot、無聲數據損壞Silent Data Corruption,是目前硬盤數據的一種嚴重數據丟失問題。

硬盤上的數據可能會神不知鬼不覺就損壞了,也沒有什么錯誤日志。

正所謂明槍易躲,暗箭難防,這種背地里犯的錯比硬盤直接咔咔宕了還危險。

不過不用怕,Minio糾刪碼采用了高速 HighwayHash 基於哈希的校驗和來防范位衰減。

附錄3:Springboot集成MinIO基礎實現

新建一個項目springboot-minio,主要代碼:

@RestController
@Slf4j
public class FileController {

    @Autowired
    private MinioClient minioClient;
    @Value("${minio.bucketName}")
    private String bucketName;

    @GetMapping("/list")
    public List<Object> list() throws Exception {
        //獲取bucket列表
        Iterable<Result<Item>> myObjects = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucketName).build());
        Iterator<Result<Item>> iterator = myObjects.iterator();
        List<Object> items = new ArrayList<>();
        String format = "{'fileName':'%s','fileSize':'%s'}";
        while (iterator.hasNext()) {
            Item item = iterator.next().get();
            items.add(JSON.parse(String.format(format, item.objectName(),
                    formatFileSize(item.size()))));
        }
        return items;
    }

    @PostMapping("/upload")
    public ResultBean upload(@RequestParam(name = "file", required = false)
                              MultipartFile[] file) {
        ResultBean resultBean = ResultBean.newInstance();
        if (file == null || file.length == 0) {
            return resultBean.error("上傳文件不能為空");
        }
        List<String> orgfileNameList = new ArrayList<>(file.length);
        for (MultipartFile multipartFile : file) {
            String orgfileName = multipartFile.getOriginalFilename();
            orgfileNameList.add(orgfileName);
            try {
                //文件上傳
                InputStream in = multipartFile.getInputStream();
                minioClient.putObject(
                        PutObjectArgs.builder().bucket(bucketName).object(orgfileName).stream(
                                in, multipartFile.getSize(), -1)
                                .contentType(multipartFile.getContentType())
                                .build());
                in.close();
            } catch (Exception e) {
                log.error(e.getMessage());
                return resultBean.error("上傳失敗");
            }
        }
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("bucketName", bucketName);
        data.put("fileName", orgfileNameList);
        return resultBean.ok("上傳成功", data);
    }

    @RequestMapping("/download/{fileName}")
    public void download(HttpServletResponse response, @PathVariable("fileName")
            String fileName) {
        InputStream in = null;
        try {
            // 獲取對象信息
            StatObjectResponse stat = minioClient.statObject(
                    StatObjectArgs.builder().bucket(bucketName).object(fileName).build());
            response.setContentType(stat.contentType());
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    URLEncoder.encode(fileName, "UTF-8"));
            //文件下載
            in = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .build());
            IOUtils.copy(in, response.getOutputStream());
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
        }
    }

    @DeleteMapping("/delete/{fileName}")
    public ResultBean delete(@PathVariable("fileName") String fileName) {
        ResultBean resultBean = ResultBean.newInstance();
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
        } catch (Exception e) {
            log.error(e.getMessage());
            return resultBean.error("刪除失敗");
        }
        return resultBean.ok("刪除成功", null);
    }

    private static String formatFileSize(long fileS) {
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString = "";
        String wrongSize = "0B";
        if (fileS == 0) {
            return wrongSize;
        }
        if (fileS < 1024) {
            fileSizeString = df.format((double) fileS) + " B";
        } else if (fileS < 1048576) {
            fileSizeString = df.format((double) fileS / 1024) + " KB";
        } else if (fileS < 1073741824) {
            fileSizeString = df.format((double) fileS / 1048576) + " MB";
        } else {
            fileSizeString = df.format((double) fileS / 1073741824) + " GB";
        }
        return fileSizeString;
    }

}

​ yml配置

minio:
  endpoint: http://10.12.105.15:9000
  accesskey: minioadmin
  secretKey: minioadmin
  bucketName: chenxin-bucket

​ 啟動Springboot項目后,調用localhost:8080/list

img

​ 用postman上傳試下,很明顯上傳成功了。

img

同理下載也是一樣,看下接口就清楚了,接口后面跟着文件名就可以下載了,當然這個

后面要做成存儲到數據庫里,這個后面我拓展出來,先會使用再說。

參考代碼:https://gitee.com/cx_gitee/springboot-minio

說明:本文會以pdf格式持續更新,更多最新尼恩3高pdf筆記,請從下面的鏈接獲取:語雀 或者 碼雲

參考文檔

https://www.jianshu.com/p/95538d262b93
http://tech.dianwoda.com/2018/12/04/fen-bu-shi-cun-chu-xi-tong-miniojian-jie/
https://www.jianshu.com/p/68ac0477291d
https://studygolang.com/articles/34762
http://docs.minio.org.cn/docs/master/distributed-minio-quickstart-guide
https://blog.csdn.net/qq_31821733/article/details/119882573
https://blog.51cto.com/zyrs/2749314
https://docs.min.io/cn/deploy-minio-on-docker-compose.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM