目录:
- 概述
- 添加依赖
- 配置参数
- 配置参数实体
- 配置MinioClient
- 封装工具类
参考/来源:
概述
MinIO是Kubernetes原生支持、分布式、高性能对象存储项目。MinIO基于Apache V2 license 100%开放源代码。MinIO的客户能够自动的、无限制、自由免费使用和集成MinIO、自由的创新和创造、自由的去修改、自由的再次发行新的版本和软件。提供丰富的部署文档、健全的SDK,以及多样化应用场景建设方案。
MinIO Java Client SDK提供简单的API来访问任何与Amazon S3兼容的对象存储服务。截至2021年01月13日,Minio官方最新版本8.0.3
,Minio中文官网最新版本7.0.2
。虽然中文官网延迟一个版本,但是并不影响其在中国用户心目中的地位。针对不熟悉英文阅读技巧的用户,尤其是行业新朋友,具有很高的实用价值。本文仅以7.0.2
作为应用版本,整合SpringBoot
工程。
最低需求:
- Java 1.8或更高版本
- Minio 7.0.2
- SpringBoot 2.0.2.RELEASE
Docker部署
参考:https://mp.weixin.qq.com/s/kvLZRqgm1lEITm1j6rzJ0A
添加依赖
通过Maven进行依赖管理,请引入如下依赖:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.0.2</version>
</dependency>
配置文件
通过yml
Minio对象存储连接参数。
## MinIO对象存储
minio:
# 地址
url: https://play.min.io
# 账号
access-key: Q3AM3UQ867SPQQA43P2F
# 密码
secret-key: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG
# 超时时间(毫秒)
connect-timeout: 60000
write-timeout: 60000
read-timeout: 60000
spring:
servlet:
multipart:
enabled: true #开启文件上传
max-file-size: 10MB #限制文件上传大小为10M
配置参数实体
通过Spring自动注入
方式,实例化properties
配置实体对象。
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import lombok.Data;
/**
* Minio配置
* @author heayan
* @version 1.0.0
* @date 2021年1月7日 下午4:42:37
*/
@Data
@Configuration
@ConfigurationProperties(prefix="minio")
public class MinioProperties {
/**
* MinIO 地址
*/
private String url;
/**
* MinIO 账号
*/
private String accessKey;
/**
* MinIO 密码
*/
private String secretKey;
/**
* 连接超时时间(毫秒)
*/
private long connectTimeout;
/**
* 写超时时间(毫秒)
*/
private long writeTimeout;
/**
* 读超时时间(毫秒)
*/
private long readTimeout;
}
配置MinioClient
创建Minio对象存储
配置类MinioConfig.java
。项目启动时自动创建Minio
连接对象,并注入Spring
容器进行管理。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.minio.MinioClient;
import io.minio.errors.InvalidEndpointException;
import io.minio.errors.InvalidPortException;
import lombok.extern.slf4j.Slf4j;
/**
* 创建Minio连接并注册至Spring容器
* @author heayan
* @version 1.0.0
* @date 2021年1月7日 下午4:37:19
*/
@Configuration
@Slf4j
public class MinioConfig {
@Autowired
private MinioProperties properties;
@Bean
MinioClient minioClient(){
MinioClient client = null;
try {
client = new MinioClient(
properties.getUrl(),
properties.getAccessKey(),
properties.getSecretKey()
);
client.setTimeout(properties.getConnectTimeout(),
properties.getWriteTimeout(),
properties.getReadTimeout());
} catch (InvalidEndpointException | InvalidPortException e) {
// TODO Auto-generated catch block
log.error(e.getMessage(), e);
}
return client;
}
}
封装工具类
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.xmlpull.v1.XmlPullParserException;
import io.minio.MinioClient;
import io.minio.Result;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidArgumentException;
import io.minio.errors.InvalidBucketNameException;
import io.minio.errors.InvalidEncryptionMetadataException;
import io.minio.errors.NoResponseException;
import io.minio.errors.RegionConflictException;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.Item;
import io.minio.messages.Upload;
import lombok.extern.slf4j.Slf4j;
/**
* Minio对象存储 工具类
*
* @author heayan
* @version 1.0.0
* @date 2021年1月7日 下午3:58:06
*/
@Component
@Slf4j
public class MinioUtils {
/**
* <h2>存储桶命名规则:</h2>
* 1. 值区名称必须介于3到63个字符之间。
* 2. 值区名称只能包含小写字母,数字,点(。)和连字符(-)。
* 3. 值区名称必须以字母或数字开头和结尾。
* 4. 存储桶名称不得格式化为IP地址(例如192.168.5.4)。
* 5. 值区名称不能以开头xn--(对于2020年2月之后创建的值区)。
* 6. 存储桶名称在分区中必须唯一。分区是区域的分组。AWS当前具有三个分区:(aws标准区域),aws-cn(中国区域)和aws-us-gov (AWS GovCloud [美国]区域)。
* 与Amazon S3 Transfer Acceleration一起使用的存储桶的名称中不能带有点(。)。有关传输加速的更多信息,请参阅Amazon S3传输加速。
*
*/
/**
* 连接对象
*/
@Autowired
private MinioClient minioClient;
/**
* 存储桶API:创建一个新的存储桶
* @param bucketName 存储桶名称
* @author heayan
* @throws XmlPullParserException
* @throws IOException
* @throws InternalException
* @throws ErrorResponseException
* @throws NoResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InvalidBucketNameException
* @throws InvalidKeyException
* @throws RegionConflictException
* @date 2021年1月7日 下午8:27:49
*/
public void makeBucket(String bucketName) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException, RegionConflictException {
boolean found = minioClient.bucketExists(bucketName);
if (found) {
log.info("[Minio] {} already exists", bucketName);
} else {
minioClient.makeBucket(bucketName);
log.info("[Minio] {} is created successfully", bucketName);
}
}
/**
* 存储桶API:列出所有存储桶。
* @return
* @author heayan
* @throws Exception
* @date 2021年1月7日 下午8:28:36
*/
public List<String> listBuckets() throws Exception{
List<String> buckets = null;
List<Bucket> bucketList = minioClient.listBuckets();
buckets = bucketList.stream().map(e -> e.name()).collect(Collectors.toList());
log.info("[Minio] The bucket list is : {}", JacksonUtils.obj2json(buckets));
return buckets;
}
/**
* 存储桶API:检查存储桶是否存在
* @param bucketName 存储桶名称
* @return
* @author heayan
* @throws XmlPullParserException
* @throws IOException
* @throws InternalException
* @throws ErrorResponseException
* @throws NoResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InvalidBucketNameException
* @throws InvalidKeyException
* @date 2021年1月7日 下午8:28:55
*/
public boolean bucketExists(String bucketName) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException{
boolean found = false;
found = minioClient.bucketExists(bucketName);
if (found) {
log.info("[Minio] {} already exists", bucketName);
} else {
log.info("[Minio] {} does not exist", bucketName);
}
return found;
}
/**
*
* 存储桶API:删除一个存储桶
* <p>注意: - removeBucket不会删除存储桶里的对象,你需要通过removeObject API来删除它们。</p>
* @param bucketName 存储桶名称
* @author heayan
* @throws XmlPullParserException
* @throws IOException
* @throws InternalException
* @throws ErrorResponseException
* @throws NoResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InvalidBucketNameException
* @throws InvalidKeyException
* @date 2021年1月7日 下午8:29:14
*/
public void removeBucket(String bucketName) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException{
boolean found = minioClient.bucketExists(bucketName);
if (found) {
minioClient.removeBucket(bucketName);
log.info("[Minio] {} is removed successfully", bucketName);
} else {
log.info("[Minio] {} does not exist", bucketName);
}
}
/**
* 存储桶API:列出某个存储桶中的所有对象
* @param bucketName 存储桶名称
* @return
* @author heayan
* @throws Exception
* @date 2021年1月7日 下午8:31:32
*/
public Iterable<Result<Item>> listObjects(String bucketName) throws Exception{
Iterable<Result<Item>> myObjects = null;
// 检查存储桶是否存在。
boolean found = minioClient.bucketExists(bucketName);
if (found) {
// 列出存储桶里的对象
myObjects = minioClient.listObjects(bucketName);
List<String> objects = new ArrayList<String>();
for (Result<Item> result : myObjects) {
Item item = result.get();
objects.add(new StringBuffer()
.append(item.lastModified())
.append(",")
.append(item.objectName())
.toString());
}
log.info("[Minio] Objects list is : {}", JacksonUtils.obj2json(objects));
} else {
log.info("[Minio] {} does not exist", bucketName);
}
return myObjects;
}
/**
* 存储桶API:列出某个存储桶中的所有对象
* @param bucketName 存储桶名称
* @param prefix 对象名称的前缀
* @param recursive 是否递归查找,如果是false,就模拟文件夹结构查找
* @return
* @author heayan
* @throws Exception
* @date 2021年1月7日 下午8:31:32
*/
public Iterable<Result<Item>> listObjects(String bucketName,
String prefix) throws Exception{
Iterable<Result<Item>> myObjects = null;
// 检查存储桶是否存在。
boolean found = minioClient.bucketExists(bucketName);
if (found) {
// 列出存储桶里的对象
myObjects = minioClient.listObjects(bucketName, prefix);
List<String> objects = new ArrayList<String>();
for (Result<Item> result : myObjects) {
Item item = result.get();
objects.add(new StringBuffer()
.append(item.lastModified())
.append(",")
.append(item.objectName())
.toString());
}
log.info("[Minio] Objects list is : {}", JacksonUtils.obj2json(objects));
} else {
log.info("[Minio] {} does not exist", bucketName);
}
return myObjects;
}
/**
* 存储桶API:列出存储桶中被部分上传的对象
* @param bucketName 存储桶名称
* @return
* @author heayan
* @throws Exception
* @date 2021年1月7日 下午8:31:55
*/
public Iterable<Result<Upload>> listIncompleteUploads(String bucketName) throws Exception{
Iterable<Result<Upload>> myObjects = null;
// 检查存储桶是否存在。
boolean found = minioClient.bucketExists(bucketName);
if (found) {
// 列出存储桶中所有未完成的multipart上传的的对象。
myObjects = minioClient.listIncompleteUploads(bucketName);
List<String> objects = new ArrayList<String>();
for (Result<Upload> result : myObjects) {
Upload upload = result.get();
objects.add(new StringBuffer()
.append(upload.uploadId())
.append(", ")
.append(upload.objectName())
.toString());
}
log.info("[Minio] Objects list is : {}", JacksonUtils.obj2json(objects));
} else {
log.info("[Minio] {} does not exist", bucketName);
}
return myObjects;
}
/**
* 文件对象API: 以流的形式下载一个对象
* @param bucketName 存储桶名称
* @param objectName 存储桶里的对象名称
* @return InputStream
* @author heayan
* @throws Exception
* @date 2021年1月7日 下午8:33:53
*/
public InputStream getObject(String bucketName, String objectName) throws Exception{
InputStream stream = null;
// 调用statObject()来判断对象是否存在。
// 如果不存在, statObject()抛出异常,
// 否则则代表对象存在。
minioClient.statObject(bucketName, objectName);
// 获取objectName的输入流。
stream = minioClient.getObject(bucketName, objectName);
log.info("[Minio] Get object is : {}", stream);
return stream;
}
/**
* 文件对象API: 下载并将文件保存到本地
* @param bucketName 存储桶名称
* @param objectName 存储桶里的对象名称
* @param fileName 目标文件名称 示例:photo.jpg
* @author heayan
* @throws XmlPullParserException
* @throws IOException
* @throws InternalException
* @throws ErrorResponseException
* @throws NoResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InvalidBucketNameException
* @throws InvalidKeyException
* @throws InvalidArgumentException
* @date 2021年1月7日 下午8:33:46
*/
public void getObject(String bucketName, String objectName, String fileName) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException, InvalidArgumentException{
// 调用statObject()来判断对象是否存在。
// 如果不存在, statObject()抛出异常,
// 否则则代表对象存在。
minioClient.statObject(bucketName, objectName);
// 获取objectName的流并保存到fileName文件中。
minioClient.getObject(bucketName, objectName, fileName);
log.info("[Minio] Get object {} finished!", objectName);
}
/**
* 文件对象API: 以流的形式下载一个AES加密对象,并进行解密
* <p>在给定的存储桶中获取整个加密对象的数据作为InputStream,然后用传入的master key解密和加密对象关联的content key。
* 然后创建一个含有InputStream和Cipher的CipherInputStream。这个Cipher被初始为用于使用content key进行解密,
* 所以CipherInputStream会在返回数据前,尝试读取数据并进行解密。所以read()方法返回的是处理过的原始对象数据。</p>
* <p>CipherInputStream必须用完关闭,否则连接不会被释放。</p>
*
* @param bucketName 存储桶名称
* @param objectName 存储桶里的对象名称
* @param secKey SecretKey类型的数据
* @author heayan
* @throws XmlPullParserException
* @throws IOException
* @throws InternalException
* @throws ErrorResponseException
* @throws NoResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InvalidBucketNameException
* @throws InvalidKeyException
* @throws InvalidEncryptionMetadataException
* @throws InvalidAlgorithmParameterException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws NoSuchPaddingException
* @throws InvalidArgumentException
* @date 2021年1月7日 下午8:33:39
*/
public InputStream getObject(String bucketName, String objectName, SecretKey secKey) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException, InvalidArgumentException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidEncryptionMetadataException{
InputStream stream = null;
// 调用statObject()来判断对象是否存在。
// 如果不存在, statObject()抛出异常,
// 否则则代表对象存在。
minioClient.statObject(bucketName, objectName);
// 获取对象数据并保存到photo.jpg
stream = minioClient.getObject(bucketName, objectName, secKey);
log.info("[Minio] Successfully get object {}/{}", bucketName, objectName);
return stream;
}
/**
* 文件对象API: 通过InputStream上传对象
* <p>前端上传文件时,推荐此方法。</p>
* <p>
* 单个对象的最大大小限制在5TB。putObject在对象大于5MiB时,自动使用multiple parts方式上传。这样,当上传失败时,
* 客户端只需要上传未成功的部分即可(类似断点上传)。上传的对象使用MD5SUM签名进行完整性验证。
* </p>
* @param bucketName 存储桶名称
* @param objectName 存储桶里的对象名称
* @param stream 要上传的流
* @param contentType Content type
* @author heayan
* @throws XmlPullParserException
* @throws IOException
* @throws InternalException
* @throws ErrorResponseException
* @throws NoResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InvalidBucketNameException
* @throws InvalidKeyException
* @throws RegionConflictException
* @throws InvalidArgumentException
* @date 2021年1月7日 下午8:33:28
*/
public void putObject(String bucketName,
String objectName,
InputStream stream,
String contentType) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException, RegionConflictException, InvalidArgumentException{
//如果存储桶不存在,则进行创建,创建后文件上传
boolean found = minioClient.bucketExists(bucketName);
if(!found){
minioClient.makeBucket(bucketName);
}
minioClient.putObject(bucketName, objectName, stream, contentType);
log.info("[Minio] Put object {}/{} success, please wait a moment!", bucketName, objectName);
}
/**
* 文件对象API: 通过文件上传到对象中
* <p>本地上传文件时,推荐此方法。</p>
* @param bucketName
* @param objectName 示例:island.jpg
* @param fileName 示例:/mnt/photos/island.jpg
* @author heayan
* @throws XmlPullParserException
* @throws IOException
* @throws InternalException
* @throws ErrorResponseException
* @throws NoResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InvalidBucketNameException
* @throws InvalidKeyException
* @throws RegionConflictException
* @throws InvalidArgumentException
* @date 2021年1月7日 下午8:33:20
*/
public void putObject(String bucketName, String objectName, String fileName) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException, RegionConflictException, InvalidArgumentException{
//如果存储桶不存在,则进行创建,创建后文件上传
boolean found = minioClient.bucketExists(bucketName);
if(!found){
minioClient.makeBucket(bucketName);
}
minioClient.putObject(bucketName, objectName, fileName);
log.info("[Minio] Put object {}/{} success, please wait a moment!", bucketName, objectName);
}
/**
* 文件对象API: 通过文件流上传AES加密对象
*
* <p>
* 拿到流的数据,使用随机生成的content key进行加密,并上传到指定存储桶中。同时将加密后的content key和iv做为加密对象有header也上传到存储桶中。
* content key使用传入到该方法的master key进行加密。如果对象大于5MB,客户端会自动进行multi part上传。
* </p>
*
* @param bucketName 存储桶名称
* @param objectName 存储桶里的对象名称
* @param stream 要上传的流
* @param size 要上传的流的大小
* @param contentType Content type
* @param key 用AES初使化的对象SecretKey
* @author heayan
* @throws XmlPullParserException
* @throws IOException
* @throws InternalException
* @throws ErrorResponseException
* @throws NoResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InvalidBucketNameException
* @throws InvalidKeyException
* @throws RegionConflictException
* @throws InvalidAlgorithmParameterException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws NoSuchPaddingException
* @throws InvalidArgumentException
* @date 2021年1月7日 下午8:33:00
*/
public void putObject(String bucketName,
String objectName,
InputStream stream,
long size,
String contentType,
SecretKey secKey) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException, RegionConflictException, InvalidArgumentException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException{
//如果存储桶不存在,则进行创建,创建后文件上传
boolean found = minioClient.bucketExists(bucketName);
if(!found){
minioClient.makeBucket(bucketName);
}
minioClient.putObject(bucketName, objectName, stream, size, contentType, secKey);
log.info("[Minio] Put object {}/{} success, please wait a moment!", bucketName, objectName);
}
/**
* 删除一个对象
* @param bucketName 存储桶名称
* @param objectName 存储桶里的对象名称
* @author heayan
* @throws XmlPullParserException
* @throws IOException
* @throws InternalException
* @throws ErrorResponseException
* @throws NoResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InvalidBucketNameException
* @throws InvalidKeyException
* @date 2021年1月7日 下午8:32:51
*/
public void removeObject(String bucketName, String objectName) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException{
// 从bucketName中删除objectName。
minioClient.removeObject(bucketName, objectName);
log.info("[Minio] Successfully removed {}/{}", bucketName, objectName);
}
/**
* 删除多个对象
* @param bucketName 存储桶名称
* @param objectNames 含有要删除的多个object名称的迭代器对象
* @return Iterable 含有多个删除错误结果的迭代器对象
* @author heayan
* @throws XmlPullParserException
* @throws IOException
* @throws InternalException
* @throws ErrorResponseException
* @throws NoResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InvalidBucketNameException
* @throws InvalidKeyException
* @date 2021年1月7日 下午8:32:40
*/
public Iterable<Result<DeleteError>> removeObject(String bucketName, Iterable<String> objectNames) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException{
Iterable<Result<DeleteError>> errorResults = null;
// 删除存储桶里的多个对象
errorResults = minioClient.removeObject(bucketName, objectNames);
log.info("[Minio] Successfully removed {}/{}", bucketName, objectNames);
for (Result<DeleteError> errorResult : errorResults) {
DeleteError error = errorResult.get();
log.info("[Minio] Failed to remove '" + error.objectName() + "'. Error:" + error.message());
}
return errorResults;
}
/**
* 删除一个未完整上传的对象
* @param bucketName 存储桶名称
* @param objectName 存储桶里的对象名称
* @author heayan
* @throws XmlPullParserException
* @throws IOException
* @throws InternalException
* @throws ErrorResponseException
* @throws NoResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InvalidBucketNameException
* @throws InvalidKeyException
* @date 2021年1月7日 下午8:32:31
*/
public void removeIncompleteUpload(String bucketName, String objectName) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException{
// 从存储桶中删除名为objectName的未完整上传的对象。
minioClient.removeIncompleteUpload(bucketName, objectName);
log.info("[Minio] Successfully removed all incomplete upload session of {}/{}", bucketName, objectName);
}
/**
* 通过文件流方式上传文件
*
* @param bucket
* @param objectName
* @param stream
* @param contentType
* @author heayan
* @throws XmlPullParserException
* @throws IOException
* @throws InvalidArgumentException
* @throws RegionConflictException
* @throws InternalException
* @throws ErrorResponseException
* @throws NoResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws InvalidBucketNameException
* @throws InvalidKeyException
* @date 2021年1月11日 下午6:08:32
*/
public void upload(String bucket, String objectName, InputStream stream, String contentType) throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, NoResponseException, ErrorResponseException, InternalException, RegionConflictException, InvalidArgumentException, IOException, XmlPullParserException{
putObject(bucket, objectName, stream, contentType);
}
/**
* 通过文件流方式下载
* <p>特别说明:重载该方法时,必须关闭文件流。</p>
* @param path
* @param filename
* @param HttpServletResponse
* @throws Exception
*/
public void download(HttpServletResponse response,
String bucket,
String objectName,
String fileName) throws Exception{
//获取文件流
InputStream is = getObject(bucket, objectName);
getObject(bucket, objectName, "C:\\Users\\wushu\\Desktop\\111.jpg");
//设置响应信息
response.reset();
response.setCharacterEncoding("utf-8");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
OutputStream os = response.getOutputStream();
// 返回文件流
try {
log.info("-->chagndu :" + is.available());
byte[] b = new byte[1024];
int len = 0;
while ((len = is.read(b)) != -1) {
os.write(b, 0, len);
}
os.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
log.error(e.getMessage(), e);
throw e;
} finally {
try {
if (os != null) {
os.close();
}
if (is != null) {
is.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
log.error(e.getMessage(), e);
}
}
}
}
控制类示例
参考:http://www.macrozheng.com/#/technology/minio_use
/**
* Created by macro on 2019/12/25.
*/
@Api(tags = "MinioController", description = "MinIO对象存储管理")
@Controller
@RequestMapping("/minio")
public class MinioController {
private static final Logger LOGGER = LoggerFactory.getLogger(MinioController.class);
@Value("${minio.endpoint}")
private String ENDPOINT;
@Value("${minio.bucketName}")
private String BUCKET_NAME;
@Value("${minio.accessKey}")
private String ACCESS_KEY;
@Value("${minio.secretKey}")
private String SECRET_KEY;
@ApiOperation("文件上传")
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public CommonResult upload(@RequestParam("file") MultipartFile file) {
try {
//创建一个MinIO的Java客户端
MinioClient minioClient = new MinioClient(ENDPOINT, ACCESS_KEY, SECRET_KEY);
boolean isExist = minioClient.bucketExists(BUCKET_NAME);
if (isExist) {
LOGGER.info("存储桶已经存在!");
} else {
//创建存储桶并设置只读权限
minioClient.makeBucket(BUCKET_NAME);
minioClient.setBucketPolicy(BUCKET_NAME, "*.*", PolicyType.READ_ONLY);
}
String filename = file.getOriginalFilename();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
// 设置存储对象名称
String objectName = sdf.format(new Date()) + "/" + filename;
// 使用putObject上传一个文件到存储桶中
minioClient.putObject(BUCKET_NAME, objectName, file.getInputStream(), file.getContentType());
LOGGER.info("文件上传成功!");
MinioUploadDto minioUploadDto = new MinioUploadDto();
minioUploadDto.setName(filename);
minioUploadDto.setUrl(ENDPOINT + "/" + BUCKET_NAME + "/" + objectName);
return CommonResult.success(minioUploadDto);
} catch (Exception e) {
LOGGER.info("上传发生错误: {}!", e.getMessage());
}
return CommonResult.failed();
}
@ApiOperation("文件删除")
@RequestMapping(value = "/delete", method = RequestMethod.POST)
@ResponseBody
public CommonResult delete(@RequestParam("objectName") String objectName) {
try {
MinioClient minioClient = new MinioClient(ENDPOINT, ACCESS_KEY, SECRET_KEY);
minioClient.removeObject(BUCKET_NAME, objectName);
return CommonResult.success(null);
} catch (Exception e) {
e.printStackTrace();
}
return CommonResult.failed();
}
}