<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
MinIO
是一個高效能的物件儲存原生支援 Kubernetes
部署的解決方案。 MinIO
提供了一個 Amazon Web Services S3
相容 API
並支援所有核心 S3
功能。
MinIO
物件儲存使用 buckets
來組織物件。 儲存桶類似於檔案系統中的資料夾或目錄,其中每個 桶可以容納任意數量的物件。 MinIO
儲存桶提供 與 AWS S3
儲存桶相同的功能。
其中 MinIO
的優勢有:
高效能:
MinIO
是全球領先的物件儲存先鋒,在標準硬體上,讀/寫速度上高達183 GB / 秒
和 171 GB / 秒
。
可延伸性:
MinIO
利用了web
縮放器的來之不易的知識,為物件儲存帶來了簡單的儲存縮放模型, 在 MinIO
, 擴充套件從單個群集開始,該群集可以與其他MinIO
群集聯合以建立全域性名稱空間, 並在需要時可以跨越多個不同的資料中心。 通過新增更多叢集可以擴充套件名稱空間, 更多機架,直到實現目標。
雲原生支援:
MinIO
是在過去4年的時間內從0開始打造的一款軟體 ,符合一切原生雲端計算的架構和構建過程,並且包含最新的雲端計算的全新的技術和概念。 其中包括支援Kubernetes
、微服和多租戶的的容器技術。使物件儲存對於 Kubernetes
更加友好。
原始碼開放與企業級支援:
MinIO
基於Apache V2 license 100%
開放原始碼 。 這就意味著 MinIO
的客戶能夠自動的、無限制、自由免費使用和整合MinIO
、自由的創新和創造、 自由的去修改、自由的再次發行新的版本和軟體. 確實, MinIO
強有力的支援和驅動了很多世界500強的企業。 此外,其部署的多樣性和專業性提供了其他軟體無法比擬的優勢。
在實驗開始前請確保安裝完成了 minio
:
首先新建一個 SpringBoot
專案,在 pom
中引入 minio
依賴:
<dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.2.1</version> </dependency>
在組態檔中,宣告出 minio
的資訊:
minio: url: http://192.168.40.169:9000 # minio設定的地址,埠9000,注意不是控制檯的埠 accessKey: minioadmin # 賬號 secretKey: minioadmin # 密碼 bucketName: test-bucket # MinIO桶名字
下面建立一個設定類,對 MinioClient
進行建立:
@Data @Configuration @ConfigurationProperties(prefix = "minio") public class MinioConfig { /** * 服務地址 */ private String url; /** * 使用者名稱 */ private String accessKey; /** * 密碼 */ private String secretKey; /** * 儲存桶名稱 */ private String bucketName; @Bean public MinioClient getMinioClient() throws Exception { MinioClient minioClient = MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build(); //判斷桶是否存在,不存在則新建 if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())){ minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucketName) .build()); } return minioClient; } }
下面建立一個工具類 MinioTool
將常用的操作封裝在工具類中:
@Component public class MinioTool { @Autowired private MinioClient minioClient; @Autowired private MinioConfig minioConfig; /** * 檢視儲存bucket是否存在 * * @param bucketName 儲存bucket * @return boolean */ public Boolean bucketExists(String bucketName) { Boolean found; try { found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); } catch (Exception e) { e.printStackTrace(); return false; } return found; } /** * 建立儲存bucket * * @param bucketName 儲存bucket名稱 * @return Boolean */ public Boolean makeBucket(String bucketName) { try { minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 刪除儲存bucket * * @param bucketName 儲存bucket名稱 * @return Boolean */ public Boolean removeBucket(String bucketName) { try { minioClient.removeBucket(RemoveBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 檢視檔案物件 * * @param bucketName 儲存bucket名稱 * @return 儲存bucket內檔案物件資訊 */ public Iterable<Result<Item>> listObjects(String bucketName) { Iterable<Result<Item>> results = minioClient.listObjects( ListObjectsArgs.builder().bucket(bucketName).build()); return results; } /** * 批次刪除檔案物件 * * @param bucketName 儲存bucket名稱 * @param objects 物件名稱集合 */ public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) { List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList()); Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build()); return results; } /** * 檔案上傳 * 檔名稱相同會覆蓋 * @param file 檔案 * @return Boolean */ public Boolean upload(MultipartFile file, String fileName) { try { if (!bucketExists(minioConfig.getBucketName())) { makeBucket(minioConfig.getBucketName()); } PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName) .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build(); minioClient.putObject(objectArgs); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 檔案下載 * * @param fileName 檔名稱 * @param res response * @return Boolean */ public void download(String fileName, HttpServletResponse res) { GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(minioConfig.getBucketName()) .object(fileName).build(); try (GetObjectResponse response = minioClient.getObject(objectArgs)) { byte[] buf = new byte[1024]; int len; try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) { while ((len = response.read(buf)) != -1) { os.write(buf, 0, len); } os.flush(); byte[] bytes = os.toByteArray(); res.setCharacterEncoding("utf-8"); //設定強制下載不開啟 res.setContentType("application/force-download"); res.addHeader("Content-Disposition", "attachment;fileName=" + fileName); try (ServletOutputStream stream = res.getOutputStream()) { stream.write(bytes); stream.flush(); } } } catch (Exception e) { e.printStackTrace(); } } public String getFileUrl(String fileName){ return StringFormatter.concat(minioConfig.getUrl(), "/", minioConfig.getBucketName(), "/", fileName).getValue(); } }
編寫測試介面,進行測試:
@Component public class MinioTool { @Autowired private MinioClient minioClient; @Autowired private MinioConfig minioConfig; /** * 檢視儲存bucket是否存在 * * @param bucketName 儲存bucket * @return boolean */ public Boolean bucketExists(String bucketName) { Boolean found; try { found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); } catch (Exception e) { e.printStackTrace(); return false; } return found; } /** * 建立儲存bucket * * @param bucketName 儲存bucket名稱 * @return Boolean */ public Boolean makeBucket(String bucketName) { try { minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 刪除儲存bucket * * @param bucketName 儲存bucket名稱 * @return Boolean */ public Boolean removeBucket(String bucketName) { try { minioClient.removeBucket(RemoveBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 檢視檔案物件 * * @param bucketName 儲存bucket名稱 * @return 儲存bucket內檔案物件資訊 */ public Iterable<Result<Item>> listObjects(String bucketName) { Iterable<Result<Item>> results = minioClient.listObjects( ListObjectsArgs.builder().bucket(bucketName).build()); return results; } /** * 批次刪除檔案物件 * * @param bucketName 儲存bucket名稱 * @param objects 物件名稱集合 */ public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) { List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList()); Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build()); return results; } /** * 檔案上傳 * 檔名稱相同會覆蓋 * @param file 檔案 * @return Boolean */ public Boolean upload(MultipartFile file, String fileName) { try { if (!bucketExists(minioConfig.getBucketName())) { makeBucket(minioConfig.getBucketName()); } PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName) .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build(); minioClient.putObject(objectArgs); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 檔案下載 * * @param fileName 檔名稱 * @param res response * @return Boolean */ public void download(String fileName, HttpServletResponse res) { GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(minioConfig.getBucketName()) .object(fileName).build(); try (GetObjectResponse response = minioClient.getObject(objectArgs)) { byte[] buf = new byte[1024]; int len; try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) { while ((len = response.read(buf)) != -1) { os.write(buf, 0, len); } os.flush(); byte[] bytes = os.toByteArray(); res.setCharacterEncoding("utf-8"); //設定強制下載不開啟 res.setContentType("application/force-download"); res.addHeader("Content-Disposition", "attachment;fileName=" + fileName); try (ServletOutputStream stream = res.getOutputStream()) { stream.write(bytes); stream.flush(); } } } catch (Exception e) { e.printStackTrace(); } } public String getFileUrl(String fileName){ return StringFormatter.concat(minioConfig.getUrl(), "/", minioConfig.getBucketName(), "/", fileName).getValue(); } }
測試上傳檔案:
如果使用 返回的 url 直接存取檔案,可以發現返回許可權不足:
這裡需要改一下 Bucket
的 Access Policy
,預設為 private
,可以修改為 public
便無需認證,但安全性無法保證:
再次進行存取,檔案就可以開啟了:
如果需要保持 private
,可以通過 MinioClient
進行下載,使用 download
測試介面下載檔案:http://localhost:8080/file/download/20cab4e3979eba6003f95aca0dc75c63.jpg
到此這篇關於SpringBoot使用Minio進行檔案儲存的實現的文章就介紹到這了,更多相關SpringBoot Minio檔案儲存內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45