1、创建一个桶Bucket,名字叫test
Buckets - Create Bucket
2、创建一个访问用户
Identity - Users - Create User
(1)创建一个用户user001,12345678
(2)设置权限
consoleAdmin:控制台管理
diagnostics:诊断
readwrite:读写
(3)为用户设置Access Keys
Access Key:VsKN1asPH1l4iNiL
Secret Key:6tO8VuGDxZsSBXBiakrsm4rRCRTrvHBE
3、pom文件引入
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.3</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.10.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.8.10</version>
</dependency>
minio依赖okhttp和kotlin,springboot自带依赖版本可能比较老。
引用jar包的工具类网上找一个参考参考。
4、application.yml文件添加
#minio配置
minio:
url: http://192.168.3.203:9998
access-key: VsKN1asPH1l4iNiL
secret-key: 6tO8VuGDxZsSBXBiakrsm4rRCRTrvHBE
bucket-name: test
#设置文件上传大小
spring:
servlet:
multipart:
max-file-size: 50MB
max-request-size: 50MB
5、minio配置类
MinioClientConfig.java
package com.example.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.minio.MinioClient;
@Configuration
public class MinioClientConfig {
@Value("${minio.url}")
private String url;
@Value("${minio.access-key}")
private String accessKey;
@Value("${minio.secret-key}")
private String secretKey;
/**
* 注入minio客户端
*/
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(url)
.credentials(accessKey, secretKey)
.build();
}
}
ObjectItem.java
package com.example.domain;
import lombok.Data;
/**
* minio文件对象的实体类
*/
@Data
public class ObjectItem {
private String objectName;
private Long size;
}
6、minio工具类
MinioUtil.java
package com.example.utils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;
import com.example.domain.ObjectItem;
import io.minio.BucketExistsArgs;
import io.minio.GetObjectArgs;
import io.minio.GetObjectResponse;
import io.minio.ListObjectsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveBucketArgs;
import io.minio.RemoveObjectsArgs;
import io.minio.Result;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
@Component
public class MinioUtil {
@Autowired
private MinioClient minioClient;
/**
* 判断bucket是否存在
*/
public boolean existBucket(String bucketName) {
try {
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
return exists;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 创建存储bucket
*
* @param bucketName 存储bucket名称
* @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
*
* @param bucketName 存储bucket名称
* @return Boolean
*/
public Boolean removeBucket(String bucketName) {
try {
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* description: 上传文件(浏览器上传)
*
* @param multipartFile
* @return : java.lang.String
*
*/
public List<String> upload(MultipartFile[] multipartFile, String bucketName) {
List<String> names = new ArrayList<>(multipartFile.length);
for (MultipartFile file : multipartFile) {
String fileName = file.getOriginalFilename();
String[] split = fileName.split("\\.");
if (split.length > 1) {
fileName = split[0] + "_" + System.currentTimeMillis() + "." + split[1];
} else {
fileName = fileName + System.currentTimeMillis();
}
InputStream in = null;
try {
in = file.getInputStream();
minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName)
.stream(in, in.available(), -1).contentType(file.getContentType()).build());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
names.add(fileName);
}
return names;
}
/**
* 下载文件(适用于浏览器下载)
*
* @param fileName
* @return : org.springframework.http.ResponseEntity<byte []>
*/
public ResponseEntity<byte[]> download(String fileName, String bucketName) {
ResponseEntity<byte[]> responseEntity = null;
InputStream in = null;
ByteArrayOutputStream out = null;
try {
in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
out = new ByteArrayOutputStream();
IOUtils.copy(in, out);
// 封装返回值
byte[] bytes = out.toByteArray();
HttpHeaders headers = new HttpHeaders();
try {
//告示浏览器文件的打开方式是下载
headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
headers.setContentLength(bytes.length);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setAccessControlExposeHeaders(Arrays.asList("*"));
responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return responseEntity;
}
/**
* 查看文件对象
*
* @param bucketName 存储bucket名称
* @return 存储bucket内文件对象信息
*/
public List<ObjectItem> listObjects(String bucketName) {
Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());
List<ObjectItem> objectItems = new ArrayList<>();
try {
for (Result<Item> result : results) {
Item item = result.get();
ObjectItem objectItem = new ObjectItem();
objectItem.setObjectName(item.objectName());
objectItem.setSize(item.size());
objectItems.add(objectItem);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return objectItems;
}
/**
* 批量删除文件对象
*
* @param bucketName 存储bucket名称
* @param objects 对象名称集合
*/
public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) {
List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());
Iterable<Result<DeleteError>> results = minioClient
.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
return results;
}
/**
* 文件下载(适用于浏览器下载,方式二)
* @param fileName 文件名称
* @param bucketName 桶名称
* @param res response
* @return
*/
public void download(String fileName, String bucketName, 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");
// 设置强制下载不打开
// res.setContentType("application/force-download");
res.setContentLength(bytes.length);
res.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
//告示浏览器文件的打开方式是下载
res.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "utf-8"));
try (ServletOutputStream stream = res.getOutputStream()) {
stream.write(bytes);
stream.flush();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
7、minio测试类
MinioController.java
package com.example.web;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.example.domain.ObjectItem;
import com.example.utils.MinioUtil;
import io.minio.Result;
import io.minio.messages.DeleteError;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@Api(description = "minio测试接口")
@RestController
@RequestMapping("/minio")
public class MinioController {
@Autowired
private MinioUtil minioUtil;
@Value("${minio.url}")
private String address;
// @Value("${minio.bucket-name}")
// private String bucketName;
@ApiOperation("判断bucket是否存在")
@PostMapping(value="/existBucket")
public boolean existBucket(String bucketName) {
return minioUtil.existBucket(bucketName);
}
@ApiOperation("创建存储bucket")
@PostMapping(value="/makeBucket")
public boolean makeBucket(String bucketName) {
return minioUtil.makeBucket(bucketName);
}
@ApiOperation("删除存储bucket")
@PostMapping(value="/removeBucket")
public boolean removeBucket(String bucketName) {
return minioUtil.removeBucket(bucketName);
}
@ApiOperation("上传文件(浏览器上传)")
@PostMapping(value="/upload", headers="content-type=multipart/form-data")
public List<String> upload(@ApiParam(name="attach", value="attach", required=true) @RequestPart("attach") MultipartFile file, String bucketName) {
//在swagger测试,只能传单个文件
List<String> names = minioUtil.upload(new MultipartFile[] {file}, bucketName);
//List<String> names = minioUtil.upload(file, bucketName);
return names;
}
@ApiOperation("下载文件(适用于浏览器下载)")
@PostMapping(value="/download")
public ResponseEntity<byte[]> download(String fileName, String bucketName) {
return minioUtil.download(fileName, bucketName);
}
@ApiOperation("下载文件(适用于浏览器下载,方式二)")
@PostMapping(value="/download2")
public void download2(String fileName, String bucketName, HttpServletResponse res) {
minioUtil.download(fileName, bucketName, res);
}
@ApiOperation("查看bucket文件对象")
@PostMapping(value="/listObjects")
public List<ObjectItem> listObjects(String bucketName) {
return minioUtil.listObjects(bucketName);
}
@ApiOperation("批量删除文件对象")
@PostMapping(value="/removeObjects")
public Iterable<Result<DeleteError>> removeObjects(String bucketName, @RequestParam("fileNames") List<String> fileNames) {
return minioUtil.removeObjects(bucketName, fileNames);
}
}
8、测试
上传:
下载:
目前工具类只有浏览器上传、下载功能,没有接口上传下载功能,还要根据使用场景完善。
参考资料:
springboot整合minio_qianQueen的博客-CSDN博客
springboot整合minio分布式存储_kill-java的博客-CSDN博客