SpringBoot整合Minio實(shí)現(xiàn)上傳文件的完整步驟記錄
Minio
上傳文件如果不使用云服務(wù)的話,需要本地搭建,一般選擇 FastDFS 但是 FastDFS 安裝比較復(fù)雜,今天了解一款安裝使用更簡單的存儲系統(tǒng) MinIO
MinIO 是一款高性能、分布式的對象存儲系統(tǒng). 它是一款軟件產(chǎn)品, 可以100%的運(yùn)行在標(biāo)準(zhǔn)硬件。即X86等低成本機(jī)器也能夠很好的運(yùn)行MinIO。
MinIO與傳統(tǒng)的存儲和其他的對象存儲不同的是:它一開始就針對性能要求更高的私有云標(biāo)準(zhǔn)進(jìn)行軟件架構(gòu)設(shè)計(jì)。因?yàn)镸inIO一開始就只為對象存儲而設(shè)計(jì)。所以他采用了更易用的方式進(jìn)行設(shè)計(jì),它能實(shí)現(xiàn)對象存儲所需要的全部功能,在性能上也更加強(qiáng)勁,它不會為了更多的業(yè)務(wù)功能而妥協(xié),失去MinIO的易用性、高效性。 這樣的結(jié)果所帶來的好處是:它能夠更簡單的實(shí)現(xiàn)局有彈性伸縮能力的原生對象存儲服務(wù)。
MinIO在傳統(tǒng)對象存儲用例(例如輔助存儲,災(zāi)難恢復(fù)和歸檔)方面表現(xiàn)出色。同時(shí),它在機(jī)器學(xué)習(xí)、大數(shù)據(jù)、私有云、混合云等方面的存儲技術(shù)上也獨(dú)樹一幟。當(dāng)然,也不排除數(shù)據(jù)分析、高性能應(yīng)用負(fù)載、原生云的支持。
在中國:阿里巴巴、騰訊、百度、中國聯(lián)通、華為、中國移動等等9000多家企業(yè)也都在使用MinIO產(chǎn)品
安裝 Minio
使用docker安裝
拉取鏡像
docker pull minio/minio
啟動
docker run -p 9000:9000 -p 9001:9001 -d --name minio -v /opt/docker/minio/data:/data -v /opt/docker/minio/config:/root/.minio -e "MINIO_ROOT_USER=minio" -e "MINIO_ROOT_PASSWORD=minio@123456" minio/minio server /data --console-address ":9000" --address ":9001"
使用9000端口 登錄控制臺

創(chuàng)建存儲桶

設(shè)置桶權(quán)限



創(chuàng)建 Java 客戶端
依賴
<dependencies>
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- minio依賴 -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.1</version>
</dependency>
<!-- hutool工具類 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.1.2</version>
</dependency>
<!-- 壓縮圖片 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<!-- 工具類依賴 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>com.github.davidcarboni</groupId>
<artifactId>encrypted-</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>配置文件
spring:
application:
name: minio-demo
servlet:
multipart:
max-file-size: 20MB
max-request-size: 200MB
server:
port: 8088
minio:
endpoint: http://你的ip:9001
accessKey: minio
secretKey: minio@123456
nginxHost: http://你的域名配置文件配置類
package com.sqm.minio_demo.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "minio")
@Component
@Data
public class MinioProperties {
/**
* 連接地址
*/
private String endpoint;
/**
* 用戶名
*/
private String accessKey;
/**
* 密碼
*/
private String secretKey;
/**
* 域名
*/
private String nginxHost;
}創(chuàng)建 minio 客戶端
package com.sqm.minio_demo.config;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(MinioProperties.class)
public class MinioConfig {
@Autowired
private MinioProperties minioProperties;
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint(minioProperties.getEndpoint())
.credentials(minioProperties.getAccessKey(),minioProperties.getSecretKey())
.build();
}
}文件地址返回路徑實(shí)體類
package com.sqm.minio_demo.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UploadResponse {
private String minIoUrl;
private String nginxUrl;
}上傳文件工具類
package com.sqm.minio_demo.util;
import cn.hutool.core.date.DateUtil;
import com.sqm.minio_demo.config.MinioProperties;
import com.sqm.minio_demo.entity.UploadResponse;
import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Optional;
import java.util.Random;
@Component
@Slf4j
public class MinioUtil {
@Autowired
private MinioProperties minioProperties;
@Autowired
private MinioClient minioClient;
private final Long maxSize = (long) (1024 * 1024);
/**
* 創(chuàng)建bucket
*/
public void createBucket(String bucketName) throws Exception {
if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
}
/**
* 上傳文件
*/
public UploadResponse uploadFile(MultipartFile file, String bucketName) throws Exception {
//判斷文件是否為空
if (null == file || 0 == file.getSize()) {
return null;
}
//判斷存儲桶是否存在 不存在則創(chuàng)建
createBucket(bucketName);
//文件名
String originalFilename = file.getOriginalFilename();
//新的文件名 = 時(shí)間戳_隨機(jī)數(shù).后綴名
assert originalFilename != null;
long now = System.currentTimeMillis() / 1000;
String fileName = DateUtil.format(DateUtil.date(),"yyyyMMdd")+"_"+ now + "_" + new Random().nextInt(1000) +
originalFilename.substring(originalFilename.lastIndexOf("."));
//開始上傳
log.info("file壓縮前大小:{}",file.getSize());
if (file.getSize() > maxSize) {
FileItemFactory fileItemFactory = new DiskFileItemFactory();
FileItem fileItem = fileItemFactory.createItem(fileName, "text/plain", true, fileName);
OutputStream outputStream = fileItem.getOutputStream();
Thumbnails.of(file.getInputStream()).scale(1f).outputFormat(originalFilename.substring(originalFilename.lastIndexOf(".")+1)).outputQuality(0.25f).toOutputStream(outputStream);
file = new CommonsMultipartFile(fileItem);
}
log.info("file壓縮后大小:{}",file.getSize());
minioClient.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;
return new UploadResponse(url, urlHost);
}
/**
* 獲取全部bucket
*
* @return
*/
public List<Bucket> getAllBuckets() throws Exception {
return minioClient.listBuckets();
}
/**
* 根據(jù)bucketName獲取信息
*
* @param bucketName bucket名稱
*/
public Optional<Bucket> getBucket(String bucketName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, InternalException, ErrorResponseException, ServerException, XmlParserException, ServerException {
return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
}
/**
* 根據(jù)bucketName刪除信息
*
* @param bucketName bucket名稱
*/
public void removeBucket(String bucketName) throws Exception {
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
}
/**
* 獲取?件外鏈
*
* @param bucketName bucket名稱
* @param objectName ?件名稱
* @param expires 過期時(shí)間 <=7
* @return url
*/
public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).expiry(expires).build());
}
/**
* 獲取?件
*
* @param bucketName bucket名稱
* @param objectName ?件名稱
* @return ?進(jìn)制流
*/
public InputStream getObject(String bucketName, String objectName) throws Exception {
return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
}
/**
* 上傳?件
*
* @param bucketName bucket名稱
* @param objectName ?件名稱
* @param stream ?件流
* @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream) throws
Exception {
minioClient.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-minioClient-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream, long
size, String contextType) throws Exception {
minioClient.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-minioClient-api-reference.html#statObject
*/
public StatObjectResponse getObjectInfo(String bucketName, String objectName) throws Exception {
return minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
}
/**
* 刪除?件
*
* @param bucketName bucket名稱
* @param objectName ?件名稱
* @throws Exception https://docs.minio.io/cn/java-minioClient-apireference.html#removeObject
*/
public void removeObject(String bucketName, String objectName) throws Exception {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
}
/***
* 上傳視頻
* @param file
* @param bucketName
* @return
* @throws Exception
*/
public UploadResponse uploadVideo(MultipartFile file, String bucketName) throws Exception {
//判斷文件是否為空
if (null == file || 0 == file.getSize()) {
return null;
}
//判斷存儲桶是否存在 不存在則創(chuàng)建
createBucket(bucketName);
//文件名
String originalFilename = file.getOriginalFilename();
//新的文件名 = 時(shí)間戳_隨機(jī)數(shù).后綴名
assert originalFilename != null;
long now = System.currentTimeMillis() / 1000;
String fileName = DateUtil.format(DateUtil.date(),"yyyyMMdd")+"_"+ now + "_" + new Random().nextInt(1000) +
originalFilename.substring(originalFilename.lastIndexOf("."));
//開始上傳
log.info("file大小:{}",file.getSize());
minioClient.putObject(
PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
file.getInputStream(), file.getSize(), -1)
.contentType("video/mp4")
.build());
String url = minioProperties.getEndpoint() + "/" + bucketName + "/" + fileName;
String urlHost = minioProperties.getNginxHost() + "/" + bucketName + "/" + fileName;
return new UploadResponse(url, urlHost);
}
}測試上傳文件 Controller
package com.sqm.minio_demo.controller;
import com.sqm.minio_demo.entity.ResultData;
import com.sqm.minio_demo.entity.UploadResponse;
import com.sqm.minio_demo.util.MinioUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@Slf4j
public class TestController {
@Autowired
private MinioUtil minioUtil;
/**
* @author: xx
* @date: 2022/5/25 15:32
* @description: 上傳文件
*/
@PostMapping("/upload")
public ResultData minioUpload(@RequestParam(value = "file") MultipartFile file){
UploadResponse response = null;
try {
response = minioUtil.uploadFile(file, "bucket01");
} catch (Exception e) {
log.error("上傳失敗",e);
}
return ResultData.ok(response);
}
/**
* @author: xx
* @date: 2022/5/25 15:32
* @description: 上傳視頻
*/
@PostMapping("/uploadVideo")
public ResultData uploadVideo(@RequestParam(value = "file") MultipartFile file){
UploadResponse response = null;
try {
response = minioUtil.uploadVideo(file, "video-test");
} catch (Exception e) {
log.error("上傳失敗",e);
}
return ResultData.ok(response);
}
}測試上傳


控制臺也可以看到上傳的視頻

總結(jié)
到此這篇關(guān)于SpringBoot整合Minio實(shí)現(xiàn)上傳文件的文章就介紹到這了,更多相關(guān)SpringBoot整合Minio上傳文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何查看Linux上正在運(yùn)行的所有Java程序列表
在linux操作時(shí),經(jīng)常要查看運(yùn)行的項(xiàng)目的進(jìn)程和端口,下面這篇文章主要給大家介紹了關(guān)于如何查看Linux上正在運(yùn)行的所有Java程序列表的相關(guān)資料,需要的朋友可以參考下2023-10-10
SpringBoot實(shí)現(xiàn)發(fā)送電子郵件
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)發(fā)送電子郵件,電子郵件是—種用電子手段提供信息交換的通信方式,是互聯(lián)網(wǎng)應(yīng)用最廣的服務(wù)。通過網(wǎng)絡(luò)的電子郵件系統(tǒng),用戶可以非??焖俚姆绞?,與世界上任何一個(gè)角落的網(wǎng)絡(luò)用戶聯(lián)系,下面就來看看SpringBoot如何實(shí)現(xiàn)發(fā)送電子郵件吧2022-01-01
基于SpringBoot項(xiàng)目實(shí)現(xiàn)Docker容器化部署的主要步驟
部署SpringBoot項(xiàng)目到Docker容器涉及選擇Java運(yùn)行時(shí)環(huán)境的基礎(chǔ)鏡像、構(gòu)建包含應(yīng)用程序的Docker鏡像、編寫Dockerfile、使用docker build命令構(gòu)建鏡像和使用docker run命令運(yùn)行Docker容器等步驟2024-10-10
springBoot Junit測試用例出現(xiàn)@Autowired不生效的解決
這篇文章主要介紹了springBoot Junit測試用例出現(xiàn)@Autowired不生效的解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09
Java調(diào)用Pytorch實(shí)現(xiàn)以圖搜圖功能
這篇文章主要為大家詳細(xì)介紹了Java如何調(diào)用Pytorch實(shí)現(xiàn)以圖搜圖功能,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2023-06-06
在Spring Boot中使用Spark Streaming進(jìn)行實(shí)時(shí)數(shù)據(jù)處理和流式計(jì)算的步驟
這篇文章主要介紹了在Spring Boot中使用Spark Streaming進(jìn)行實(shí)時(shí)數(shù)據(jù)處理和流式計(jì)算,通過本文的介紹,我們了解了在Spring Boot中使用Spark Streaming進(jìn)行實(shí)時(shí)數(shù)據(jù)處理和流式計(jì)算的詳細(xì)步驟,需要的朋友可以參考下2024-03-03
Java實(shí)現(xiàn)二維碼功能的實(shí)例代碼
今天這篇文章,主要是利用Java實(shí)現(xiàn)二維碼功能,本文思路清晰,需要的朋友參考下2017-02-02
java IO實(shí)現(xiàn)電腦搜索、刪除功能的實(shí)例
下面小編就為大家?guī)硪黄猨ava IO實(shí)現(xiàn)電腦搜索、刪除功能的實(shí)例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-12-12

