Minio的使用教程
Minio介紹
Minlo
是一個基于Apache License v2.0開源協(xié)議的對象存儲服務。它兼容亞馬遜S3云存儲服務接口,非常適合于存儲大容量非結構化的數(shù)據,例如圖片、視頻、日志文件、備份數(shù)據和容器/虛擬機鏡像等,而一個對象文件可以是任意大小,從幾kb到最大5T不等。 對于中小型企業(yè),如果不選擇存儲上云,那么 MinIO
是個不錯的選擇,麻雀雖小,五臟俱全。當然 MinIO
除了直接作為對象存儲使用,還可以作為云上對象存儲服務的網關層,無縫對接到 Amazon S3
等。
優(yōu)點:
- 部署簡單:一個single二進制文件即是一切,還可支持各種平臺。
- Minio支持海量存儲,可按zone擴展(原zone不受任何影響),支持單個對象最大5TB;
- 兼容Amazon S3接口,充分考慮開發(fā)人員的需求和體驗;
- 讀寫性能優(yōu)異
Minio基礎概念
概念名稱 | 對應含義解釋 |
---|---|
Object | 存儲的基本對象;比如文件、圖片等等 |
Bucket | 用于存儲 Object 的邏輯空間;相互之間互相隔離;類似于系統(tǒng)中的頂層文件夾 |
Drive | 即存儲數(shù)據的磁盤;所有的對象數(shù)據都會存儲在 Drive 里面 |
Set | 即一組 Drive 的集合;分布式部署根據集群規(guī)模自動劃分一個或多個 Set |
Linux安裝Minio
1.獲取minio安裝包
wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio-20241029160148.0.0-1.x86_64.rpm -O minio.rpm
2.安裝minio
rpm -ivh minio.rpm
Minio配置
1.修改minio服務配置文件
vim /usr/lib/systemd/system/minio.service
注釋Type、User、Group
修改后的文件如下:
[Unit] Description=MinIO Documentation=https://docs.min.io Wants=network-online.target After=network-online.target AssertFileIsExecutable=/usr/local/bin/minio [Service] #Type=notify WorkingDirectory=/usr/local #User=minio-user #Group=minio-user ProtectProc=invisible EnvironmentFile=-/etc/default/minio ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES Restart=always LimitNOFILE=1048576 MemoryAccounting=no TasksMax=infinity TimeoutSec=infinity SendSIGKILL=no [Install] WantedBy=multi-user.target
參數(shù)解釋:
AssertFileIsExecutable
:可以在此參數(shù)聲明的配置文件中添加minio服務啟動時所需一些參數(shù)
ExecStart
:該參數(shù)用于配置Minio服務的啟動命令,其中$MINIO_OPTS
、$MINIO_VOLUMES
,均引用于EnvironmentFile
中的變量。
Restart
:設置服務在失敗時自動重啟,這里是always
,意味著總是重啟。
2.配置
1.編寫EnvironmentFile中指定路徑下的配置文件
vim /etc/default/minio
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadmin
MINIO_VOLUMES=/data
MINIO_OPTS="--console-address :9001"
解釋:
MINIO_ROOT_USER
:登錄后臺管理平臺的用戶名
MINIO_ROOT_PASSWORD
:登錄后臺管理平臺的密碼
MINIO_VOLUMES
:指定數(shù)據存儲路徑,需確保指定的路徑是存在的
MINIO_OPTS
:指定管理頁面的地址的端口號
2.創(chuàng)建minio數(shù)據存儲路徑
mkdir /data
3.防火墻設置開放端口
#開放minio的9000和9001端口
firewall-cmd --zone=public --add-port=9000/tcp --add-port=9001/tcp --permanent
#重新加載防火墻規(guī)則
firewall-cmd --reload
#查看開放的端口
firewall-cmd --list-ports
4.讓systemctl檢查配置并重新加載系統(tǒng)服務的配置文件
systemctl daemon - reload
#設置minio服務自啟動
systemctl enable minio
#啟動minio服務
systemctl start minio
#查看minio服務狀態(tài)
systemctl status minio
Minio后臺管理系統(tǒng)使用
賬號密碼就是etc/default/minio
文件里面配置的MINIO_ROOT_USER
和MINIO_ROOT_PASSWORD
介紹
存儲桶管理界面介紹
Access Policy:訪問策略
- public:允許所有人對該存儲桶進行讀寫操作
- private:只允許所有者操作該存儲桶,其他人不能讀寫該存儲桶
- custom:自定義存儲桶的訪問權限,如:只允許所有者寫,但允許所有人讀,自定義訪問權限有格式要求,格式為JSON
Encryption:加密策略,可選值:Disabled、SSE-S3、SSE-KMS
Reported Usage:存儲桶使用情況,即使用的內存大小
Quota:配置存儲桶限制的數(shù)據量
Browse Bucket:瀏覽存儲桶列表
存儲桶列表界面
介紹
Upload File:上傳文件
Upload Folder:上傳文件夾
Refresh:刷新
Download:下載文件
Share:共享圖片(可以設置共享的連接的時效性)
Preview:查看圖片
Delete:刪除圖片
Object Info:對象信息,包含了名稱、大小、上次修改時間、內容類型等等信息
文件上傳
創(chuàng)建
1.創(chuàng)建存儲桶
創(chuàng)建時可選值
Bucket Name:存儲桶名稱
Versioning:允許在同一鍵下保留同一對象的多個版本。
Object Locking:確保一旦對象存儲在特定的存儲桶中,它們就不能被刪除,這是為了滿足數(shù)據保留和法律保留的要求。這種特性或策略只能在創(chuàng)建存儲桶的時候設置,一旦存儲桶被創(chuàng)建,就不能再對這個特性進行更改。
Quota:限制存儲桶中的數(shù)據量。
2.上傳圖片
1.選擇Upload File
2.選擇要上傳的文件
3.上傳后可以看到界面的右上角有文件的上傳進度
訪問上傳的圖片
訪問minio的存儲桶的圖片的url格式就是
首先在存儲桶瀏覽列表復制存儲桶中文件的路徑
然后再URL打上自己的Minio服務的主機IP加上端口號最后拼接上我們復制的文件地址
192.168.181.31:9000/test/房間-臥室-1.jpg
訪問報錯?
原因分析:因為我們的存儲桶的訪問權限為私有的所以我們訪問不了這個存儲桶中的圖片\文件,所以我們要修改訪問權限
步驟:
1.點擊存儲桶瀏覽列表右上角的設置
2.編輯存儲桶的訪問權限,我們選擇自定義權限
再存儲桶管理界面介紹中就介紹到了存儲桶的訪問權限,所以這里我們選擇自定義,權限為:只允許所有者寫,但允許所有人讀,但是
自定義訪問權限,需要使用一個規(guī)定格式的JSON字符串進行描述,具體格式可參考官方文檔。
如:允許(Allow
)所有人(*
)讀取(s3:GetObject
)指定桶(test
)的所有內容
{ "Statement" : [ { "Action" : "s3:GetObject", "Effect" : "Allow", "Principal" : "*", "Resource" : "arn:aws:s3:::test/*" } ], "Version" : "2012-10-17" }
按照上圖片進行配置之后,再去訪問圖片,就可以正常訪問了
Minio Java SDK使用
Minio提供了多種語言的SDK供開發(fā)者使用,具體內容可參考官方文檔。
1. 在Spring Boot項目的pom中引入Minio依賴
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.2.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
創(chuàng)建一個類方法測試,然后執(zhí)行查看是否上傳成功
public class App { public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException { try { //構造MinIO Client MinioClient minioClient = MinioClient.builder() .endpoint("http://192.168.10.101:9000")//填寫你的地址 .credentials("minioadmin", "minioadmin")//填寫你的賬號、密碼 .build(); //創(chuàng)建hello-minio桶 boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket("hello-minio").build()); if (!found) { //創(chuàng)建hello-minio桶 minioClient.makeBucket(MakeBucketArgs.builder().bucket("hello-minio").build()); //設置hello-minio桶的訪問權限 //JDK15之后的特性,三引號 String policy = """ { "Statement" : [ { "Action" : "s3:GetObject", "Effect" : "Allow", "Principal" : "*", "Resource" : "arn:aws:s3:::hello-minio/*" } ], "Version" : "2012-10-17" }"""; minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket("hello-minio").config(policy).build()); } else { System.out.println("Bucket 'hello-minio' already exists."); } //上傳圖片 minioClient.uploadObject( UploadObjectArgs.builder() .bucket("hello-minio") .object("公寓-外觀.jpg") .filename("D:\\workspace\\hello-minio\\src\\main\\resources\\公寓-外觀.jpg") //這個文件填寫你電腦要上傳的圖片的路徑 .build()); System.out.println("上傳成功"); } catch (MinioException e) { System.out.println("Error occurred: " + e); } } }
如果使用的JDK版本不高與15的話可以用這一段代替
String policy = "{\n" + " \"Statement\" : [ {\n" + " \"Action\" : \"s3:GetObject\",\n" + " \"Effect\" : \"Allow\",\n" + " \"Principal\" : \"*\",\n" + " \"Resource\" : \"arn:aws:s3:::hello-minio/*\"\n" + " } ],\n" + " \"Version\" : \"2012-10-17\"\n" + "}";
2. 在application.yml或properties中添加Minio配置參數(shù)
#項目名 server: servlet: context-path: /minioDemo minio: endpoint: http://192.168.181.29:9000 #minio地址 access-key: minioadmin #用戶名 secret-key: minioadmin #密碼 bucket-name: lease #存儲的minio名稱(自定義)
3. 創(chuàng)建Minio配置類和配置參數(shù)類
3.1. 創(chuàng)建配置類MinioConfiguration
@Configuration @EnableConfigurationProperties(MinioProperties.class)//單個配置參數(shù)類掃描 //@ConfigurationPropertiesScan("com.waitforme.lease.common.minio")掃描一個路徑下的所有配置參數(shù)類 //@EnableConfigurationProperties、@ConfigurationPropertiesScan兩個注解的作用都是為了注冊配置參數(shù)類,根據需要使用其一即可 public class MinioConfiguration { @Autowired private MinioProperties properties; @Bean public MinioClient minioClient() { return MinioClient .builder() .endpoint(properties.getEndpoint()) .credentials(properties.getAccessKey(), properties.getSecretKey()) .build(); } }
3.2. 創(chuàng)建一個配置參數(shù)類
因為配置類中需要用到之前第二步添加的Minio的配置參數(shù),所以創(chuàng)建它
@ConfigurationProperties(prefix = "minio") @Data public class MinioProperties { private String endpoint; private String accessKey; private String secretKey; private String bucketName; }
注意:如果出現(xiàn)了如圖的錯誤提示,是因為你沒有在配置類中注冊配置參數(shù)類,所以要先進行注冊,在MinioConfiguration
類上加上@EnableConfigurationProperties
或@ConfigurationPropertiesScan
注解進行注冊
4.創(chuàng)建FileService接口及其實現(xiàn),實現(xiàn)圖片獲取、上傳、刪除邏輯
service
public interface FileService { //圖片上傳 String upload(MultipartFile file) throws Exception; //獲取圖片列表 List<String> getListObjects() throws Exception; //刪除單個圖片 Boolean deleteObject(String fileName) throws Exception; }
serviceImpl
@Service("fileService") public class FileServiceImpl implements FileService { @Autowired MinioClient minioClient; @Autowired MinioProperties properties; @Override public String upload(MultipartFile file) throws Exception { boolean bucketExists = minioClient.bucketExists( BucketExistsArgs.builder() .bucket(properties.getBucketName()).build()); if (!bucketExists) { //判斷minio中是否存在我們配置的存儲桶名稱 minioClient.makeBucket(MakeBucketArgs.builder().bucket(properties.getBucketName()).build()); //創(chuàng)建存儲桶 minioClient.setBucketPolicy( SetBucketPolicyArgs.builder() .bucket(properties.getBucketName()) .config(createBucketPolicyConfig(properties.getBucketName())).build()); //為創(chuàng)建的存儲桶設置訪問權限 } String fileName = UUID.randomUUID() + "-" + file.getOriginalFilename(); //上傳的文件名 minioClient.putObject(PutObjectArgs.builder() .bucket(properties.getBucketName()) //上傳的存儲桶名稱 .stream(file.getInputStream(), file.getSize(), -1) /*上傳的文件,三個參數(shù)分別表示: 1. 上傳的文件io流 2. 上傳的文件大小 3. -1表示我們確定了自己要上傳的文件大小后,讓minio自己自動去分配每次上傳的大小,因為minio不是一次性刪除而是分片上傳*/ .object(fileName) //上傳后的文件名 .contentType(file.getContentType()) //上傳文件類型,通過file.getContentType獲取,因為不設置的話就是steam類型,訪問的時候會下載圖片,而不是預覽圖片 .build()); //上傳文件 return String.join("/", properties.getEndpoint(), properties.getBucketName(), fileName); //join方法用于通過指定一個分割符,將傳入的的參數(shù)拼接成一串字符,可以傳入多個參數(shù) } /** * 獲取圖片列表 * @return 返回處理完的圖片數(shù)組列表 * @throws Exception 直接拋出最大的異常類 */ @Override public List<String> getListObjects() throws Exception { List<String> objectNames = new ArrayList<>(); //創(chuàng)建一個數(shù)組用于存儲獲取到的圖片 Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder() .bucket(properties.getBucketName()) .build()); //獲取指定存儲桶中的圖片列表 for (Result<Item> result : results) { Item item = result.get(); objectNames.add(String.join("/", properties.getEndpoint(), properties.getBucketName(), item.objectName())); //遍歷得到的數(shù)組,并通過指定為:http://xxx.xxx.xxx.xx:9000/bucketName/fileName.jpg的格式到數(shù)組中 } return objectNames; } /** * 刪除存儲桶中的單個圖片 * @param fileName 圖片名稱包括后綴 * @return 直接返回ture * @throws Exception */ @Override public Boolean deleteObject(String fileName) throws Exception { minioClient.removeObject(RemoveObjectArgs.builder() .bucket(properties.getBucketName()) .object(fileName) .build()); return true; } /** * @param bucketName 存儲桶名稱 * @return 返回存儲桶的訪問權限JSON字符串 * 返回值表示允許所以人讀取該存儲桶下的所有文件,沒有設置寫權限是因為默認創(chuàng)建人就是寫權限擁有者 * 其中resource中的%s表示占位符,.formatted中的就是占位符的值 */ private String createBucketPolicyConfig(String bucketName) { //三引號是jdk15添加的新功能 return """ { "Statement" : [ { "Action" : "s3:GetObject", "Effect" : "Allow", "Principal" : "*", "Resource" : "arn:aws:s3:::%s/*" } ], "Version" : "2012-10-17" } """.formatted(bucketName); } }
如果使用的JDK版本低于15可以用這段代替createBucketPolicyConfig方法里面的代碼
private String createBucketPolicyConfig(String bucketName) { String policy = String.format( "{\n" + " \"Statement\" : [ {\n" + " \"Action\" : \"s3:GetObject\",\n" + " \"Effect\" : \"Allow\",\n" + " \"Principal\" : \"*\",\n" + " \"Resource\" : \"arn:aws:s3:::%s/*\"\n" + " } ],\n" + " \"Version\" : \"2012-10-17\"\n" + "}", bucketName); return policy; }
5.創(chuàng)建Controller
@Controller public class MinioController { @Autowired MinioService minioService; @RequestMapping("/upload") public String upload(@RequestParam MultipartFile file, Model model) { try { String url = minioService.upload(file); model.addAttribute("url", url); model.addAttribute("msg", "上傳成功"); } catch (Exception e) { model.addAttribute("msg", "上傳失敗:" + e.getMessage()); } return "redirect:/list"; } @RequestMapping({"/list", ""}) public String getListObjects(Model model) throws Exception { List<String> listObjects = minioService.getListObjects(); model.addAttribute("listObjects", listObjects); model.addAttribute("msg", listObjects == null ? "獲取圖片失敗或是沒有圖片" : ""); return "index"; } @RequestMapping("/remove") @ResponseBody public Object removeObject(@RequestParam String fileName) { Map map = null; try { Boolean flag = minioService.deleteObject(fileName); map = new HashMap(); map.put("flag", flag); map.put("msg", "刪除成功"); } catch (Exception e) { map.put("msg", "刪除失敗:" + e.getMessage()); return map; } return map; } }
6.在templates中創(chuàng)建index.html頁面
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <style type="text/css"> ul{ list-style-type: none; } ul>li{ margin: 20px; } </style> <body> <div align="center"> <h1>minio的增刪改查示例</h1> <form th:action="@{/upload}" method="post" enctype="multipart/form-data"> <input type="file" name="file" required> <button type="submit">上傳圖片</button> </form> </div> <div align="center"> <h2 align="center">已上傳的圖片</h2> <ul> <li th:each="object : ${listObjects}"> <img th:src="@{${object}}" alt="11" width="450px" height="230px"> <a href="#" th:onclick="del(this,[[${object}]]);" style="padding-left: 100px">刪除</a> </li> </ul> <p id="msg" style="color: red" align="center">[[${msg}]]</p> </div> </body> <script th:src="@{/js/jquery-1.12.4.js}" type="text/javascript"></script> <script type="text/javascript"> function del(obj, url) { if (confirm("確認要刪除嗎?")) { var parts = url.split("/"); var fileName = parts[parts.length - 1]; $.getJSON("remove", "fileName=" + fileName, function (data) { if (data.flag) { $(obj).parents("li").remove(); } $("#msg").html(data.msg); }) } } </script> </html>
然后,在static中創(chuàng)建js
文件夾放入 jquery-1.12.4.js
頁面效果
遇到的錯誤
獲取圖片信息報錯?
報錯原因:因為物理機的請求時間跟服務器的時間相差太大了,簡單說就是要同步一下虛擬機的時間
解決步驟:
1.進入虛擬機,點擊右上角序號1,然后點擊root,再點擊賬號設置
2.在彈出的窗口中選擇日期和時間,然后把自動設置日期和時間、自動設置時區(qū)打開,等待時間與物理機相同即可
注意:此方案需要有網絡才能實現(xiàn)
a標簽用th:onclick="|del(this,${object})|"
報錯500?
原因分析:應該是thymeleaf
的版本問題
解決方案:替換th:onclick="|del(this,${object})|"
為th:onclick="del(this,[[${object}]]);"
<a href="#" th:onclick="del(this,[[${object}]]);" style="padding-left: 100px">刪除</a>
到此這篇關于Minio的使用的文章就介紹到這了,更多相關Minio的使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringCloud+RocketMQ實現(xiàn)分布式事務的實踐
分布式事務已經成為了我們的經常使用的。所以我們來一步一步的實現(xiàn)基于RocketMQ的分布式事務。感興趣的可以了解一下2021-10-10Java SimpleDateFormat中英文時間格式化轉換詳解
這篇文章主要為大家詳細介紹了Java SimpleDateFormat中英文時間格式化轉換,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12Java中數(shù)組轉list的兩種簡單實現(xiàn)方式
這篇文章主要介紹了兩種將數(shù)組轉換為List的方法,兩種方法分別是使用Arrays.asList()方法和使用ArrayList構造函數(shù),文中通過代碼介紹的非常詳細,需要的朋友可以參考下2025-03-03HotSpot的Java對象模型之Oop-Klass模型詳解
這篇文章主要介紹了HotSpot的Java對象模型之Oop-Klass模型詳解,在JVM層面,不僅Java類是對象,Java 方法也是對象, 字節(jié)碼常量池也是對象,一切皆是對象,JVM使用不同的oop-klass模型來表示各種不同的對象,需要的朋友可以參考下2023-08-08springboot多模塊化整合mybatis,mapper自動注入失敗問題及解決
這篇文章主要介紹了springboot多模塊化整合mybatis,mapper自動注入失敗問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01