Spring Boot集成Minio筆記

一、首先配置MinIO

1、MinIO新建Bucket,訪問控制臺如圖

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
創建訪問密鑰(就是賬號和密碼)
在這里插入圖片描述
在這里插入圖片描述

二、集成mino添加Minio客戶端依賴

1.maven構建方式在pom.xml引入jar

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

2.配置Minio連接參數

Springoot配置文件yaml添加minio配置Minio連接參數:

    # minio 參數配置minio:#是否啟用 默認值是trueenabled: true#是否https ,#如果是true,則用的是https而不是http,默認值是falsesecure: false#文件預覽地址 由于我們的MinIO服務運行在9001端口上preview: http://127.0.0.1:9001#Minio服務器地址endpoint: http://127.0.0.1:9001# 默認存儲桶bucket-name: #登錄賬號access-key: MKBgpZsb7WoLFEUTeR8y#登錄密碼secret-key: VpONfVhjGtPOUd26yPrm3ZskvuPLF4QGSTMtWRLE

(endpoint, access key, secret key,bucket name)主要是就是四個個參數,其他是因為業務需要加的參數
在這里插入圖片描述

三、編寫服務類,實現文件上傳、下載等方法

1.創建配置類,初始化MinioClient Bean

import io.minio.MinioClient;
import lombok.Data;
import okhttp3.OkHttpClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;@ConfigurationProperties(prefix = "oss.minio")
@Configuration
@Data
public class MinioConfig {/*** 服務地址*/private String endpoint;/*** 文件預覽地址*/private String preview;/*** 存儲桶名稱*/private String bucketName;/*** 用戶名*/private String accessKey;/*** 密碼*/private String secretKey;/*** 是否https ,是:true  不是:false*/private Boolean secure;/*** 初始化客戶端,獲取 MinioClient*/@Beanpublic MinioClient minioClient() throws NoSuchAlgorithmException, KeyManagementException {MinioClient.Builder minioClient = MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey);//是否https,如果是取消ssl認證if (secure) {final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {@Overridepublic void checkClientTrusted(X509Certificate[] x509Certificates, String s) {}@Overridepublic void checkServerTrusted(X509Certificate[] x509Certificates, String s) {}@Overridepublic X509Certificate[] getAcceptedIssuers() {return new X509Certificate[]{};}}};X509TrustManager x509TrustManager = (X509TrustManager) trustAllCerts[0];final SSLContext sslContext = SSLContext.getInstance("SSL");sslContext.init(null, trustAllCerts, new SecureRandom());final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();OkHttpClient.Builder builder = new OkHttpClient.Builder();builder.sslSocketFactory(sslSocketFactory, x509TrustManager);builder.hostnameVerifier((s, sslSession) -> true);OkHttpClient okHttpClient = builder.build();minioClient.httpClient(okHttpClient).region("eu-west-1");}return minioClient.build();}}

2.文件上傳接口

package priv.cl.oss.service;import org.springframework.web.multipart.MultipartFile;import java.io.InputStream;/*** @ClassName MinioFileStorageService* @Description MinioFileStorageService* @Author cl* @Date 2025/2/22 16:40*/
public interface MinIOFileStorageService {/*** 上傳圖片文件** @param prefix      文件前綴* @param filename    文件名* @param inputStream 文件流* @return 文件url*/String uploadImgFile(String prefix, String filename, InputStream inputStream);/*** 上傳html文件** @param prefix      文件前綴* @param filename    文件名* @param inputStream 文件流* @return 文件url*/String uploadHtmlFile(String prefix, String filename, InputStream inputStream);/*** 上傳文件不分類型** @param prefix        文件前綴* @param filename      文件名* @param multipartFile 文件* @return 文件url*/String uploadFileByMultipartFile(String prefix, String filename, MultipartFile multipartFile);/*** 上傳本地文件** @param prefix     文件前綴* @param objectName 對象名稱* @param fileName   本地文件路徑*/String uploadFile(String prefix, String objectName, String fileName);/*** 下載文件url到本地指定路徑** @param fileUrl 文件url* @param templatePath 指定路徑文件夾* @return path 本地文件全路徑*/String downloadFile(String fileUrl, String templatePath);/*** 下載文件** @param fileUrl 文件url* @return*/byte[] downloadFile(String fileUrl);/*** 刪除文件** @param fileUrl 文件url*/void deleteFile(String fileUrl);
}

3.文件上傳實現類

package priv.cl.oss.service;import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import priv.cl.oss.config.MinioConfig;import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;/*** @ClassName MinIOFileStorageServiceImpl* @Description MinIOFileStorageServiceImpl* @Author cl* @Date 2025/2/22 16:45*/
@Slf4j
@Service
public class MinIOFileStorageServiceImpl implements MinIOFileStorageService {private String separator = "/";@Autowiredprivate MinioClient minioClient;@Autowiredprivate MinioConfig minioConfig;/*** @param dirPath* @param filename yyyy/mm/dd/file.jpg* @return*/public String builderFilePath(String dirPath, String filename) {StringBuilder stringBuilder = new StringBuilder(50);if (!StringUtils.isEmpty(dirPath)) {stringBuilder.append(dirPath).append(separator);}SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");String todayStr = sdf.format(new Date());stringBuilder.append(todayStr).append(separator);stringBuilder.append(filename);return stringBuilder.toString();}/*** 獲取文件名* @param fileUrl* @return*/public String getFilePathByFileUrl(String fileUrl) {String filePath = fileUrl.replace(minioConfig.getEndpoint() + "/", "");int index = filePath.indexOf(separator);filePath = filePath.substring(index + 1);return filePath;}/*** 上傳圖片文件** @param prefix      文件前綴* @param filename    文件名* @param inputStream 文件流* @return url*/@Overridepublic String uploadImgFile(String prefix, String filename, InputStream inputStream) {String filePath = builderFilePath(prefix, filename);try {PutObjectArgs putObjectArgs = PutObjectArgs.builder().object(filePath).contentType("image/jpg").bucket(minioConfig.getBucketName()).stream(inputStream, inputStream.available(), -1).build();minioClient.putObject(putObjectArgs);StringBuilder urlPath = new StringBuilder(minioConfig.getPreview());urlPath.append(separator + minioConfig.getBucketName());urlPath.append(separator);urlPath.append(filePath);return urlPath.toString();} catch (Exception e) {log.error("minio put file error.", e);throw new RuntimeException("上傳文件失敗");}}/*** 上傳html文件** @param prefix      文件前綴* @param filename    文件名* @param inputStream 文件流* @return url*/@Overridepublic String uploadHtmlFile(String prefix, String filename, InputStream inputStream) {String filePath = builderFilePath(prefix, filename);try {PutObjectArgs putObjectArgs = PutObjectArgs.builder().object(filePath).contentType("text/html").bucket(minioConfig.getBucketName()).stream(inputStream, inputStream.available(), -1).build();minioClient.putObject(putObjectArgs);StringBuilder urlPath = new StringBuilder(minioConfig.getEndpoint());urlPath.append(separator + minioConfig.getBucketName());urlPath.append(separator);urlPath.append(filePath);return urlPath.toString();} catch (Exception e) {log.error("minio put file error.", e);throw new RuntimeException("上傳文件失敗");}}/*** 上傳文件不分類型** @param prefix        文件前綴* @param filename      文件名* @param multipartFile 文件流* @return url*/@Overridepublic String uploadFileByMultipartFile(String prefix, String filename, MultipartFile multipartFile) {String filePath = builderFilePath(prefix, filename);try {// 將MultipartFile轉換為InputStreamInputStream inputStream = multipartFile.getInputStream();PutObjectArgs putObjectArgs = PutObjectArgs.builder().object(filePath).contentType(multipartFile.getContentType()).bucket(minioConfig.getBucketName()).stream(inputStream, multipartFile.getSize(), -1).build();minioClient.putObject(putObjectArgs);StringBuilder urlPath = new StringBuilder(minioConfig.getPreview());urlPath.append(separator + minioConfig.getBucketName());urlPath.append(separator);urlPath.append(filePath);return urlPath.toString();} catch (Exception e) {log.error("minio put file error.", e);throw new RuntimeException("上傳文件失敗");}}/*** 上傳本地文件** @param prefix     文件前綴* @param objectName 文件名稱* @param fileName   本地文件全路徑*/@Overridepublic String uploadFile(String prefix, String objectName, String fileName) {String filePath = builderFilePath(prefix, objectName);try {UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder().bucket(minioConfig.getBucketName()).object(filePath).filename(fileName).build();minioClient.uploadObject(uploadObjectArgs);StringBuilder urlPath = new StringBuilder(minioConfig.getEndpoint());urlPath.append(separator + minioConfig.getBucketName());urlPath.append(separator);urlPath.append(filePath);return urlPath.toString();} catch (Exception e) {log.error("minio upload file error.", e);throw new RuntimeException("上傳文件失敗");}}/*** 下載文件url到本地指定文件夾** @param fileUrl      文件url* @param templatePath 指定路徑文件夾* @return path 本地文件全路徑*/@Overridepublic String downloadFile(String fileUrl, String templatePath) {String filePath = getFilePathByFileUrl(fileUrl);InputStream inputStream = null;String filename = filePath.substring(filePath.lastIndexOf(separator) + 1);try {inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(minioConfig.getBucketName()).object(filePath).build());FileOutputStream outputStream = null;outputStream = new FileOutputStream(templatePath + filename);byte[] buff = new byte[100];int rc = 0;while (true) {try {if (!((rc = inputStream.read(buff, 0, 100)) > 0)) break;} catch (IOException e) {log.error("文件read失敗");e.printStackTrace();}outputStream.write(buff, 0, rc);}outputStream.close();inputStream.close();} catch (Exception e) {log.error("minio down file error.  pathUrl:{}", fileUrl);throw new RuntimeException("下載文件url到本地指定文件夾失敗");}return templatePath + filename;}/*** 下載文件** @param fileUrl 文件全路徑* @return 文件流*/@Overridepublic byte[] downloadFile(String fileUrl) {String filePath = getFilePathByFileUrl(fileUrl);InputStream inputStream = null;try {inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(minioConfig.getBucketName()).object(filePath).build());ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();byte[] buff = new byte[100];int rc = 0;while (true) {try {if (!((rc = inputStream.read(buff, 0, 100)) > 0)) break;} catch (IOException e) {log.error("文件read失敗");e.printStackTrace();}byteArrayOutputStream.write(buff, 0, rc);}return byteArrayOutputStream.toByteArray();} catch (Exception e) {log.error("minio down file error.  pathUrl:{}", fileUrl);throw new RuntimeException("下載文件失敗");}}/*** 刪除文件** @param fileUrl 文件url*/@Overridepublic void deleteFile(String fileUrl) {String filePath = getFilePathByFileUrl(fileUrl);// 構建參數RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(filePath).build();try {minioClient.removeObject(removeObjectArgs);} catch (Exception e) {log.error("minio remove file error.  pathUrl:{}", fileUrl);throw new RuntimeException("刪除文件失敗");}}
}

4.Controller調用

@RestController
@RequestMapping("/minio")
public class MinioController {@Autowiredprivate MinIOFileStorageService minIOFileStorageServiceImpl;@GetMapping("/test")public String test(){return "Hello World";}@PostMapping("/fileupload")public String fileupload(@RequestParam MultipartFile file){// 檢查multipartFile是否為空if (file == null || file.isEmpty()) {return "文件為空,無法處理。";}// 上傳到MinIO服務器// 這里的"common"是前綴String url = minIOFileStorageServiceImpl.uploadFileByMultipartFile("common", file.getOriginalFilename(), file);return url;}}

四、測試集成

1.postman調用

在這里插入圖片描述

2.通過minio客戶端查看

在這里插入圖片描述
遇到問題
1.url無法查看在這里插入圖片描述
解決方案:
權限問題,設置成pulic,當然為了安全也可以生成訪問外鏈
在這里插入圖片描述

至此結束 ,有問題歡迎留言指出謝謝!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/71693.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/71693.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/71693.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【開源寶藏】Spring Trace 一種輕量級的日志追蹤新方式

Spring Trace&#xff1a;一種輕量級的日志追蹤新方式 一、前言 在日常開發中&#xff0c;我們常常需要在日志中標記某個請求的唯一標識&#xff08;Trace ID&#xff09;或上下文信息&#xff0c;以便快速定位問題或查看調用鏈路。傳統做法通常會使用 MDC&#xff08;Mapped…

Web網頁開發——水果忍者

1.介紹 復刻經典小游戲——水果忍者 2.預覽 3.代碼 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title&…

【Flink銀行反欺詐系統設計方案】6.用戶畫像數據與反欺詐系統的關聯思路

【Flink銀行反欺詐系統設計方案】6.用戶畫像數據與反欺詐系統的關聯思路 概要1. 用戶畫像數據與反欺詐系統的關聯思路1.1 用戶畫像數據內容1.2 數據賦能反欺詐的核心邏輯 2. 用戶畫像賦能反欺詐的3個案例2.1 案例1&#xff1a;消費習慣異常檢測2.2 案例2&#xff1a;設備/地理位…

如何在unity中完整錄制一段動畫

在動畫制作中&#xff0c;需要對接音頻部門進行音效的制作。通常需要完整且無多余幀數的動畫視頻作為時間和幀數對幀參考&#xff0c;這時候手動錄屏就會顯得不夠精確&#xff0c;這里分享一個插件錄制方法&#xff0c;可以自定義錄制起始位置&#xff0c;0幀起手完整錄制。 錄…

Jetson Orin 安裝 onnxruntime

Jetson Orin 安裝 onnxruntime onnxruntime在Jetson上安裝只需注意三件事&#xff1a; 版本&#xff01; 版本&#xff01; 還是TMD版本&#xff01; 本機環境 Jectpack : 5.1.2CUDA : 11.4cuDNN &#xff1a;8.6.0 版本說明 關于onnxruntime的版本適配不同的官方有不同的…

Manus AI : Agent 元年開啟.pdf

Manus AI : Agent 元年開啟.pdf 是由華泰證券出品的一份調研報告&#xff0c;共計23頁。報告詳細介紹了Manus AI 及 Agent&#xff0c;主要包括Manus AI 的功能、優勢、技術能力&#xff0c;Agent 的概念、架構、應用場景&#xff0c;以及 AI Agent 的類型和相關案例&#xff0…

【為什么會有 map、weakmap 類型?】

為什么會有 map、weakmap 類型? 傳統對象的局限性催生 Map?1. 鍵類型單一性?2. 有序性與迭代支持?3. 性能優化場景? 內存管理需求催生 WeakMap?1.弱引用機制?2. 私有數據存儲?3. 規避循環引用問題? 總結 傳統對象的局限性催生 Map? 1. 鍵類型單一性? 傳統對象&…

SpringSecurity認證授權完整流程

SpringSecurity認證流程&#xff1a;loadUserByUsername&#xff08;&#xff09;方法內部實現。 實現步驟&#xff1a; 構建一個自定義的service接口&#xff0c;實現SpringSecurity的UserDetailService接口。建一個service實現類&#xff0c;實現此loadUserByUsername方法。…

本地部署DeepSeek R1大數據模型知識庫

DeepSeek-V3 的綜合能力 DeepSeek-V3 在推理速度上相較歷史模型有了大幅提升。在目前大模型主流榜單中&#xff0c;DeepSeek-V3 在開源模型中位列榜首&#xff0c;與世界上最先進OpenAI 閉源模型不分伯仲。 1、下載Ollama運行大數據庫 Ollama支持 Llama 3.3, DeepSeek-R1, Phi-…

云端秘境:EC2的奇幻之旅

在一個神秘的云端世界里&#xff0c;流傳著一個傳說——只要掌握了 EC2&#xff08;Elastic Compute Cloud&#xff09; 的奧秘&#xff0c;就能召喚出強大的騎士軍團&#xff0c;在云端之上建造屬于自己的帝國。年輕的程序法師 艾倫&#xff08;Allen&#xff09;&#xff0c;…

【javaEE】多線程(基礎)

1.????前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 親愛的朋友們&#x1f44b;&#x1f44b;&#xff0c;這里是E綿綿呀????。 如果你喜歡這篇文章&#xff0c;請別吝嗇你的點贊????和收藏&#x1f4d6;&#x1f4d6;。如果你對我的…

一周學會Flask3 Python Web開發-WTForms表單驗證

鋒哥原創的Flask3 Python Web開發 Flask3視頻教程&#xff1a; 2025版 Flask3 Python web開發 視頻教程(無廢話版) 玩命更新中~_嗶哩嗶哩_bilibili 我們可以通過WTForms表單類屬性的validators屬性來實現表單驗證。 常用的WTForms驗證器 驗證器說明DataRequired(messageNo…

STM32標準庫代碼詳解之GPIO

GPIO的初始化代碼如下&#xff1a; /*開啟時鐘*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //開啟GPIOA的時鐘&#xff0c;使用外設必須開啟/*GPIO初始化*/ GPIO_InitTypeDef GPIO_InitStructure; //定義結構體變量 GPIO_InitStructure.GPIO_Mode GPIO_Mo…

華為歐拉系統 Tomcat 安裝詳解

1. 安裝或確認安裝 Java Tomcat 需要 Java 環境(JDK 或 JRE)才能運行。如果系統尚未安裝 Java,可以使用以下命令安裝 OpenJDK: # 更新軟件包索引 yum update -y# 安裝 OpenJDK 21(可根據需求安裝其他版本,如 8、11、17 等) yum install -y java-21-openjdk java-21-op…

第六課:數據庫集成:MongoDB與Mongoose技術應用

本文詳細介紹了如何在Node.js應用程序中集成MongoDB數據庫&#xff0c;并使用Mongoose庫進行數據操作。我們將涵蓋MongoDB在Ubuntu 20系統中的安裝、Bash命令的CRUD操作、Mongoose數據建模&#xff08;Schema/Model&#xff09;、關聯查詢與聚合管道&#xff0c;以及實戰案例—…

大數據學習(56)-Impala

&&大數據學習&& &#x1f525;系列專欄&#xff1a; &#x1f451;哲學語錄: 承認自己的無知&#xff0c;乃是開啟智慧的大門 &#x1f496;如果覺得博主的文章還不錯的話&#xff0c;請點贊&#x1f44d;收藏??留言&#x1f4dd;支持一下博主哦&#x1f91…

【C#】async與await介紹

1. 實例1 1.1 代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace ConsoleApp1 {class Program{static void Main(string[] args){Method1();Method2();Console.ReadKey();}public static…

【大模型基礎_毛玉仁】1.1 基于統計方法的語言模型

【大模型基礎_毛玉仁】1.1 基于統計方法的語言模型 1.語言模型基礎1.1 基于統計方法的語言模型1.1.1 n-grams 語言模型1.1.2 n-grams 的統計學原理 1.語言模型基礎 語言是概率的。語言模型&#xff08;LanguageModels, LMs&#xff09;旨在準確預測語言符號的概率。 將按照語…

JavaScript(最后一個元素的索引就是數組的長度減 1)array.length - 1

在不同的編程語言中&#xff0c;表示數組中最后一個元素的方法略有不同&#xff0c;但基本思路都是利用數組的長度或索引來實現。 以下是一些常見編程語言中獲取數組最后一個元素的方法&#xff1a; 1. JavaScript: 使用 array.length - 1 索引: 這是最常見和傳統的方法。Java…

SpringCloud中使用服務名調用場景總結

一 API Gateway 在 Spring Cloud API Gateway 中&#xff0c;通過使用 lb:// 前綴可以實現基于服務名的負載均衡路由。以下是具體的配置和使用方法&#xff1a; 1. 配置服務注冊與發現 確保你的服務已經注冊到服務注冊中心&#xff08;如 Nacos 或 Eureka&#xff09;。API …