一、首先配置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,當然為了安全也可以生成訪問外鏈
至此結束 ,有問題歡迎留言指出謝謝!