👉 這是一個或許對你有用的社群
《專案實戰(影片)》:從書中學,往事上“練” 《網際網路高頻面試題》:面朝簡歷學習,春暖花開 《架構 x 系統設計》:摧枯拉朽,掌控面試高頻場景題 《精進 Java 學習指南》:系統學習,網際網路主流技術棧 《必讀 Java 原始碼專欄》:知其然,知其所以然

👉這是一個或許對你有用的開源專案國產 Star 破 10w+ 的開源專案,前端包括管理後臺 + 微信小程式,後端支援單體和微服務架構。功能涵蓋 RBAC 許可權、SaaS 多租戶、資料許可權、商城、支付、工作流、大屏報表、微信公眾號、ERP、CRM、AI 大模型等等功能:
Boot 多模組架構:https://gitee.com/zhijiantianya/ruoyi-vue-pro Cloud 微服務架構:https://gitee.com/zhijiantianya/yudao-cloud 影片教程:https://doc.iocoder.cn 【國內首批】支援 JDK 17/21 + SpringBoot 3.3、JDK 8/11 + Spring Boot 2.7 雙版本
1. MinIO 簡介
-
相容 Amazon S3:可以使用 MinIO SDK,MinIO Client,AWS SDK 和 AWS CLI 訪問 MinIO 伺服器。 -
較強的資料保護能力:MinIO 使用 Minio Erasure Code 來防止硬體故障。 -
高度可用:MinIO 伺服器可以容忍分散式設定中高達 (N/2)-1
節點故障。 -
支援 Lambda 計算。 -
具有加密和防篡改功能:MinIO 為加密資料提供了機密性,完整性和真實性保證,而且效能開銷微乎其微。使用 AES-256-GCM,ChaCha20-Poly1305 和 AES-CBC 支援伺服器端和客戶端加密。 -
可對接後端儲存:除了 MinIO 自己的檔案系統,還支援 DAS、 JBODs、NAS、Google 雲端儲存和 Azure Blob 儲存。
基於 Spring Boot + MyBatis Plus + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
專案地址:https://github.com/YunaiV/ruoyi-vue-pro 影片教程:https://doc.iocoder.cn/video/
2. MinIO 安裝
docker run -p 9000:9000 -p 9001:9001 -d minio/minio server /data --console-address
":9000"
--address
":9001"
http://127.0.0.1:9000/login
即可訪問到 MinIO 的後端頁面:
minioadmin
。







docker run -p 9000:9000 -p 9001:9001 -d --name minio -v /Users/sang/minio/data:/data -v /Users/sang/minio/config:/root/.minio -e
"MINIO_ROOT_USER=javaboy"
-e
"MINIO_ROOT_PASSWORD=123@45678"
minio/minio server /data --console-address
":9000"
--address
":9001"

基於 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
專案地址:https://github.com/YunaiV/yudao-cloud 影片教程:https://doc.iocoder.cn/video/
3. 整合 Spring Boot
<dependency>
<groupId>
io.minio
</groupId>
<artifactId>
minio
</artifactId>
<version>
8.2.1
</version>
</dependency>
minio:
endpoint:http://localhost:9001
accessKey:javaboy
secretKey:123@45678
nginxHost:http://local.javaboy.org:9001
-
endpoint:這是 MinIO 的 API 通訊地址。 -
accessKey 和 secretKey 是通訊的使用者名稱和密碼,這跟網頁上登入時候的使用者名稱密碼一致。 -
nginxHost:這個配置用來生成上傳檔案的訪問路徑。對於這個路徑,有的小夥伴可能會有疑問,nginxHost 不就是 endpoint 嗎?為什麼還要單獨配置?因為對於檔案伺服器而言,我們上傳檔案是透過 MinIO,但是訪問的時候不一定透過 MinIO,我們可能會自己搭建一個 Nginx 伺服器,透過 Nginx 伺服器來訪問上傳後的資源,大家知道 Nginx 非常擅長於做這個事情,效率非常高。所以這裡的 nginxHost 其實是指 Nginx 的訪問路徑。
@ConfigurationProperties
(prefix =
"minio"
)
publicclassMinioProperties
{
/**
* 連線地址
*/
private
String endpoint;
/**
* 使用者名稱
*/
private
String accessKey;
/**
* 密碼
*/
private
String secretKey;
/**
* 域名
*/
private
String nginxHost;
public String getEndpoint()
{
return
endpoint;
}
publicvoidsetEndpoint(String endpoint)
{
this
.endpoint = endpoint;
}
public String getAccessKey()
{
return
accessKey;
}
publicvoidsetAccessKey(String accessKey)
{
this
.accessKey = accessKey;
}
public String getSecretKey()
{
return
secretKey;
}
publicvoidsetSecretKey(String secretKey)
{
this
.secretKey = secretKey;
}
public String getNginxHost()
{
return
nginxHost;
}
publicvoidsetNginxHost(String nginxHost)
{
this
.nginxHost = nginxHost;
}
}
@Configuration
@EnableConfigurationProperties
(MinioProperties
.
class
)
publicclassMinioConfig
{
@Autowired
private
MinioProperties minioProperties;
/**
* 獲取MinioClient
*/
@Bean
public MinioClient minioClient()
{
return
MinioClient.builder()
.endpoint(minioProperties.getEndpoint())
.credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
.build();
}
}
publicclassUploadResponse
{
private
String minIoUrl;
private
String nginxUrl;
publicUploadResponse()
{
}
publicUploadResponse(String minIoUrl, String nginxUrl)
{
this
.minIoUrl = minIoUrl;
this
.nginxUrl = nginxUrl;
}
public String getMinIoUrl()
{
return
minIoUrl;
}
publicvoidsetMinIoUrl(String minIoUrl)
{
this
.minIoUrl = minIoUrl;
}
public String getNginxUrl()
{
return
nginxUrl;
}
publicvoidsetNginxUrl(String nginxUrl)
{
this
.nginxUrl = nginxUrl;
}
}
@Component
publicclassMinioUtil
{
@Autowired
private
MinioProperties minioProperties;
@Autowired
private
MinioClient client;
/**
* 建立bucket
*/
publicvoidcreateBucket(String bucketName)throws Exception
{
if
(!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
}
/**
* 上傳檔案
*/
public UploadResponse uploadFile(MultipartFile file, String bucketName)throws Exception
{
//判斷檔案是否為空
if
(
null
== file ||
0
== file.getSize()) {
returnnull
;
}
//判斷儲存桶是否存在 不存在則建立
createBucket(bucketName);
//檔名
String originalFilename = file.getOriginalFilename();
//新的檔名 = 儲存桶檔名_時間戳.字尾名
assert
originalFilename !=
null
;
SimpleDateFormat format =
new
SimpleDateFormat(
"yyyy-MM-dd"
);
String fileName = bucketName +
"_"
+
System.currentTimeMillis() +
"_"
+ format.format(
new
Date()) +
"_"
+
new
Random().nextInt(
1000
) +
originalFilename.substring(originalFilename.lastIndexOf(
"."
));
//開始上傳
client.putObject(
PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
file.getInputStream(), file.getSize(), -
1
)
.contentType(file.getContentType())
.build());
String url = minioProperties.getEndpoint() +
"/"
+ bucketName +
"/"
+ fileName;
String urlHost = minioProperties.getNginxHost() +
"/"
+ bucketName +
"/"
+ fileName;
returnnew
UploadResponse(url, urlHost);
}
/**
* 獲取全部bucket
*
*
@return
*/
public List<Bucket> getAllBuckets()throws Exception
{
return
client.listBuckets();
}
/**
* 根據bucketName獲取資訊
*
*
@param
bucketName bucket名稱
*/
public Optional<Bucket> getBucket(String bucketName)throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, InternalException, ErrorResponseException, ServerException, XmlParserException, ServerException
{
return
client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
}
/**
* 根據bucketName刪除資訊
*
*
@param
bucketName bucket名稱
*/
publicvoidremoveBucket(String bucketName)throws Exception
{
client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
}
/**
* 獲取⽂件外鏈
*
*
@param
bucketName bucket名稱
*
@param
objectName ⽂件名稱
*
@param
expires 過期時間 <=7
*
@return
url
*/
public String getObjectURL(String bucketName, String objectName, Integer expires)throws Exception
{
return
client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).expiry(expires).build());
}
/**
* 獲取⽂件
*
*
@param
bucketName bucket名稱
*
@param
objectName ⽂件名稱
*
@return
⼆進位制流
*/
public InputStream getObject(String bucketName, String objectName)throws Exception
{
return
client.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
}
/**
* 上傳⽂件
*
*
@param
bucketName bucket名稱
*
@param
objectName ⽂件名稱
*
@param
stream ⽂件流
*
@throws
Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
*/
publicvoidputObject(String bucketName, String objectName, InputStream stream)throws
Exception
{
client.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, stream.available(), -
1
).contentType(objectName.substring(objectName.lastIndexOf(
"."
))).build());
}
/**
* 上傳⽂件
*
*
@param
bucketName bucket名稱
*
@param
objectName ⽂件名稱
*
@param
stream ⽂件流
*
@param
size ⼤⼩
*
@param
contextType 型別
*
@throws
Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
*/
publicvoidputObject
(String bucketName, String objectName, InputStream stream,
long
size, String contextType)
throws Exception
{
client.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, size, -
1
).contentType(contextType).build());
}
/**
* 獲取⽂件資訊
*
*
@param
bucketName bucket名稱
*
@param
objectName ⽂件名稱
*
@throws
Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
*/
public StatObjectResponse getObjectInfo(String bucketName, String objectName)throws Exception
{
return
client.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
}
/**
* 刪除⽂件
*
*
@param
bucketName bucket名稱
*
@param
objectName ⽂件名稱
*
@throws
Exception https://docs.minio.io/cn/java-client-apireference.html#removeObject
*/
publicvoidremoveObject(String bucketName, String objectName)throws Exception
{
client.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
}
}
@RestController
publicclassFileUploadController
{
@Autowired
MinioUtil minioUtil;
@PostMapping
(
"/upload"
)
public String fileUpload(MultipartFile file)throws Exception
{
UploadResponse bucket01 = minioUtil.uploadFile(file,
"bucket01"
);
System.out.println(
"bucket01.getMinIoUrl() = "
+ bucket01.getMinIoUrl());
System.out.println(
"bucket01.getNginxUrl() = "
+ bucket01.getNginxUrl());
return
bucket01.getMinIoUrl();
}
}

4. 配置 nginx
/Users/sang/minio/data
路徑下查詢檔案。
docker run --name nginx01 -p 8888:80 -v /Users/sang/minio/data:/usr/share/nginx/html:ro -d nginx
-
設定 Nginx 埠為 8888。 -
將 MinIO 對映到宿主機的資料卷,再次掛載到 Nginx 上去。
/usr/share/nginx/html
目錄下的,現在該目錄其實就相當於我宿主機的 /Users/sang/minio/data
目錄,所以我現在都不用修改 Nginx 的配置了,裝好之後直接使用 Nginx 即可。minio:
endpoint:http://localhost:9001
accessKey:javaboy
secretKey:123@45678
nginxHost:http://local.javaboy.org:8888

5. 小結





