Minio是一個go編寫基于Apache License v2.0開源協(xié)議的對象存儲系統(tǒng),是為海量數(shù)據(jù)存儲、人工智能、大數(shù)據(jù)分析而設(shè)計,它完全兼容Amazon S3接口,十分符合存儲大容量的非結(jié)構(gòu)化數(shù)據(jù)從幾十kb到最大5T不等。是一個小而美的開源分布式存儲軟件。
特點
簡單、可靠:Minio采用簡單可靠的集群方案,摒棄復(fù)雜的大規(guī)模的集群調(diào)度管理,減少風(fēng)險與性能瓶頸,聚焦產(chǎn)品的核心功能,打造高可用的集群、靈活的擴展能力以及超過的性能。建立眾多的中小規(guī)模、易管理的集群,支持跨數(shù)據(jù)中心將多個集群聚合成超大資源池,而非直接采用大規(guī)模、統(tǒng)一管理的分布式集群。
功能完善:Minio支持云原生,能與Kubernetes、Docker、Swarm編排系統(tǒng)良好對接,實現(xiàn)靈活部署。且部署簡單,只有一個可執(zhí)行文件,參數(shù)極少,一條命令即可啟動一個Minio系統(tǒng)。Minio為了高性能采取無元數(shù)據(jù)數(shù)據(jù)庫設(shè)計,避免元數(shù)據(jù)庫成為整個系統(tǒng)的性能瓶頸,并將故障限制在單個集群之內(nèi),從而不會涉及其他集群。Minio同時完全兼容S3接口,因此也可以作為網(wǎng)關(guān)使用,對外提供S3訪問。同時使用Minio Erasure code和checksum 來防止硬件故障。即使損失一半以上的硬盤,但是仍然可以從中恢復(fù)。分布式中也允許(N/2)-1個節(jié)點故障。
docker+rancher部署minio集群
在rancher上創(chuàng)建三個minio服務(wù),這三個選擇的服務(wù)器ip是三臺不同的服務(wù)器ip,在主機調(diào)度中進行選擇不同的主機
端口映射:
配置環(huán)境變量:
主機調(diào)度
每個指定不同的主機,三臺機器分別運行一個minio
配置數(shù)據(jù)卷
在三臺主機主機的host文件中添加host對應(yīng)關(guān)系
ip1 minio-1
ip2 minio-2
ip3 minio-3
數(shù)據(jù)卷配置
網(wǎng)絡(luò)
使用主機網(wǎng)絡(luò):是
入庫命令
server --console-address :9090 http://minio-{1…3}/data{1…2}
安裝ngxin負載均衡訪問minio在rancher上創(chuàng)建nginx服務(wù)
數(shù)據(jù)卷映射
進入主機目錄配置nginx,
vi /mnt/nginx/conf.d
內(nèi)容如下:
worker_processes 1;
events {
worker_connections 1024;
}
http{
#上面安裝主機的三臺機器記得修改
upstream http_minio_back{
server ip1:9000;
server ip2:9000;
server ip3:9000;
}
server{
listen 6555;
server_name localhost;
ignore_invalid_headers off;
#配置成上傳文件不限制大小
client_max_body_size 0;
proxy_buffering off;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_connect_timeout 300;
proxy_http_version 1.1;
chunked_transfer_encoding off;
proxy_ignore_client_abort on;
proxy_pass http_minio_back
}
}
}
}
數(shù)據(jù)卷配置引入conf.d
springboot+minio 實例如下:
pom.xml
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.0.3</version>
</dependency>
application.yml配置:
spring:
# 配置文件上傳大小限制
servlet:
multipart:
max-file-size: 500MB
max-request-size: 500MB
oss:
endpoint: ${ENDPOINT:http://nginx的ip:nginx的端口號}
access-key: ${ACCESS_KEY:minio}
secret-key: ${SECRET_KEY:minio}
minio配置類
@Configuration
@ApiModel(value = "minio配置")
public class MinIoClientConfig {
@Value("${oss.endpoint}")
private String url;
@Value("${oss.access-key}")
private String accessKey;
@Value("${oss.secret-key}")
private String secretKey;
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint(url)
.credentials(accessKey, secretKey)
.build();
}
}
編寫工具類用于將公用方法寫到工具類中,實現(xiàn)調(diào)用
import cn.hutool.core.io.FastByteArrayOutputStream;
import com.alibaba.nacos.common.util.UuidUtils;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
@Component
@Slf4j
@RequiredArgsConstructor
public class MinioUtil {
//必須使用注入的方式否則會出現(xiàn)空指針
@Autowired
MinioClient minioClient;
/**
* 查看存儲bucket是否存在
* bucketName 需要傳入桶名
* @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;
}
/**
* 創(chuàng)建存儲bucket
* bucketName 需要傳入桶名
* @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
* bucketName 需要傳入桶名
* @return Boolean
*/
public Boolean removeBucket(String bucketName) {
try {
minioClient.removeBucket(RemoveBucketArgs.builder()
.bucket(bucketName)
.build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 獲取全部bucket
*/
public List<Bucket> getAllBuckets() {
try {
List<Bucket> buckets = minioClient.listBuckets();
return buckets;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 文件上傳
*
* @param file 文件
* BucketName 需要傳入桶名
* @return Boolean
*/
public String upload(MultipartFile file) {
String originalFilename = file.getOriginalFilename();
if (StringUtils.isBlank(originalFilename)){
throw new RuntimeException();
}
String fileName = UuidUtils.generateUuid() + originalFilename.substring(originalFilename.lastIndexOf("."));
String objectName = "sssss" + "/" + fileName;
try {
PutObjectArgs objectArgs = PutObjectArgs.builder().bucket("BucketName").object(objectName)
.stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
//文件名稱相同會覆蓋
minioClient.putObject(objectArgs);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return objectName;
}
/**
* 預(yù)覽
* @param fileName
* BucketName 需要傳入桶名
* @return
*/
public String preview(String fileName){
// 查看文件地址
GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket("BucketName").object(fileName).method(Method.GET).build();
try {
String url = minioClient.getPresignedObjectUrl(build);
return url;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 文件下載
* @param fileName 文件名稱
* BucketName 需要傳入桶名
* @param res response
* @return Boolean
*/
public void download(String fileName, HttpServletResponse res) {
GetObjectArgs objectArgs = GetObjectArgs.builder().bucket("BucketName")
.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");
// 設(shè)置強制下載不打開
// 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();
}
}
/**
* 查看文件對象
* BucketName 需要傳入桶名
* @return 存儲bucket內(nèi)文件對象信息
*/
public List<Item> listObjects() {
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder().bucket("BucketName").build());
List<Item> items = new ArrayList<>();
try {
for (Result<Item> result : results) {
items.add(result.get());
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return items;
}
/**
* 刪除
* @param fileName
* BucketName 需要傳入桶名
* @return
* @throws Exception
*/
public boolean remove(String fileName){
try {
minioClient.removeObject( RemoveObjectArgs.builder().bucket("BucketName").object(fileName).build());
}catch (Exception e){
return false;
}
return true;
}
}
測試
@RequestMapping("/tesss")
@RestController
public class TestCon {
@Autowired
MinioUtil minioUtil;
@GetMapping("/test")
public Boolean bucketExists(String bucketName) {
return minioUtil.bucketExists(bucketName);
}
@GetMapping("/test123")
public Boolean makeBucket(String bucketName) {
return minioUtil.makeBucket(bucketName);
}
}
如果想要在上傳完成后再進行下一步的操作 ,應(yīng)該進行如下操作文章來源:http://www.zghlxwxcb.cn/news/detail-546230.html
@Async
public CompletableFuture<String> uploadFile(String bucketName, String fileName, InputStream stream,PutObjectOptions putObjectOptions){
CompletableFuture<String> future = new CompletableFuture<>();
try {
minioClient.putObject(bucketName, fileName, stream, putObjectOptions);
future.complete("上傳成功");
} catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException
| IllegalArgumentException e) {
future.completeExceptionally(e);
}
return future;
}
調(diào)用上述方法實現(xiàn)判斷文件是否上傳成功文章來源地址http://www.zghlxwxcb.cn/news/detail-546230.html
public String uploadFileCallAlgorithm(MultipartFile file, String algType,String arithmeticCode) throws IOException {
PutObjectOptions putObjectOptions = new PutObjectOptions(file.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
CompletableFuture<String> future = this.uploadFile(BucketName, fileName, file.getInputStream(), putObjectOptions);
future.thenAccept(results -> {
//此處可寫上傳文件完成后的實現(xiàn)邏輯
}).exceptionally(ex -> {
return null;
}).join();
return miningCode;
}else {
return "請上傳csv文件";
}
}
到了這里,關(guān)于SpringBoot+MinIO實現(xiàn)minio部署和使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!