MinIO实现文件上传与下载
引入依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.1.0</version>
</dependency>
工具类 MinIoUtils
@Autowired
SiMinIoProperties minIoProperties;
private static MinioClient minioClient;
/**
* 初始化minio配置
*/
@PostConstruct
public void init() {
try {
minioClient = new MinioClient(minIoProperties.getEndpoint(), minIoProperties.getAccessKey(), minIoProperties.getSecretKey());
createBucket(minIoProperties.getBucketName());
} catch (Exception e) {
e.printStackTrace();
log.error("初始化minio配置异常: {}", e.fillInStackTrace());
}
}
/**
* 判断 bucket是否存在
*
* @param bucketName: 桶名
* @return: boolean
*/
@SneakyThrows(Exception.class)
public static boolean bucketExists(String bucketName) {
return minioClient.bucketExists(bucketName);
}
/**
* 创建 bucket
*
* @param bucketName: 桶名
* @return: void
*/
@SneakyThrows(Exception.class)
public static void createBucket(String bucketName) {
boolean isExist = minioClient.bucketExists(bucketName);
if (!isExist) {
minioClient.makeBucket(bucketName);
}
}
/**
* 获取全部bucket
*
* @param :
* @return: java.util.List<io.minio.messages.Bucket>
*/
@SneakyThrows(Exception.class)
public static List<Bucket> getAllBuckets() {
return minioClient.listBuckets();
}
/**
* 文件上传
*
* @param bucketName: 桶名
* @param fileName: 文件名
* @param filePath: 文件路径
* @return: void
* @date : 2020/8/16 20:53
*/
@SneakyThrows(Exception.class)
public static void upload(String bucketName, String fileName, String filePath) {
minioClient.putObject(bucketName, fileName, filePath, null);
}
/**
* 文件上传
*
* @param bucketName: 桶名
* @param fileName: 文件名
* @param stream: 文件流
* @return: java.lang.String : 文件url地址
*/
@SneakyThrows(Exception.class)
public static String upload(String bucketName, String fileName, InputStream stream) {
minioClient.putObject(bucketName, fileName, stream, new PutObjectOptions(stream.available(), -1));
return getFileUrl(bucketName, fileName);
}
/**
* 上传时指定对应对内容类型
*
* @param bucketName 桶名
* @param folderName 文件夹名
* @param newFileName 新文件名
* @param file 文件
* @return 加密签名的url
*/
public static String uploadFile(String bucketName, String folderName, String newFileName, MultipartFile file) {
try {
//判断桶是否存在
boolean flag = bucketExists(bucketName);
if (!flag) {
createBucket(bucketName);
}
//创建文件夹并上传文件
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(bucketName)
.object(folderName + "/" + newFileName)
.contentType(ViewContentType.getContentType(file.getOriginalFilename()))
.stream(file.getInputStream(), file.getSize(), -1)
.build();
minioClient.putObject(putObjectArgs);
} catch (Exception e) {
e.printStackTrace();
}
return getFileUrl(bucketName, folderName + newFileName);
}
/**
* 私有上传
*
* @param bucketName 桶名
* @param folderName 文件夹名
* @param newFileName 新文件名
* @param file 文件
* @return
*/
public static String uploadFilePrivate(String bucketName, String folderName, String newFileName, MultipartFile file) {
//上传文件
uploadFile(bucketName, folderName, newFileName, file);
try {
//临时签名地址
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(folderName + "/" + newFileName)
.expiry(60)
.build());
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException | ErrorResponseException | ServerException | InsufficientDataException | InvalidResponseException | InternalException | InvalidBucketNameException | InvalidExpiresRangeException | XmlParserException e) {
e.printStackTrace();
}
return null;
}
/**
* 文件上传
*
* @param bucketName: 桶名
* @param file: 文件
* @return: java.lang.String : 文件url地址
*/
@SneakyThrows(Exception.class)
public static String upload(String bucketName, MultipartFile file) {
final InputStream is = file.getInputStream();
final String fileName = file.getOriginalFilename();
minioClient.putObject(bucketName, fileName, is, new PutObjectOptions(is.available(), -1));
is.close();
return getFileUrl(bucketName, fileName);
}
/**
* 删除文件
*
* @param bucketName: 桶名
* @param url: 访问地址
* @return: void
*/
@SneakyThrows(Exception.class)
public static void deleteFile(String bucketName, String url) {
String objectName = urlAnalyze(url);
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
}
/**
* 获取对象(文件)地址
*
* @param bucketName 桶名
* @param objectName 对象名
* @return 非签名加密地址
*/
@SneakyThrows(Exception.class)
public static String getObjectUrl(String bucketName, String objectName) {
return minioClient.getObjectUrl(bucketName, objectName);
}
/**
* 获取预签名对象Url
*
* @param bucketName 桶名
* @param url 访问地址
* @param expiresInSeconds 过期时间(秒)
* @return
*/
public static String getPreSignedObjectUrl(String bucketName, String url, int expiresInSeconds) {
try {
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(urlAnalyze(url))
.expiry(expiresInSeconds)
.build());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 地址解析
*
* @param url 访问地址
* @return objectName
*/
public static String urlAnalyze(String url) {
// 解析URL
URL parsedUrl;
try {
parsedUrl = new URL(URLDecoder.decode(url, "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
return "url转换异常";
}
// 提取文件夹名称和对象名称
String path = parsedUrl.getPath().substring(1);
String bucketName = "";
String objectName = "";
// 如果路径中包含斜杠,则表示存在文件夹
if (path.contains("/")) {
bucketName = path.substring(0, path.indexOf("/"));
objectName = path.substring(path.indexOf("/") + 1);
} else {
objectName = path;
}
//System.out.println("Bucket名称:" + bucketName);
//System.out.println("对象名称:" + objectName);
return objectName;
}
/**
* 获取存储桶中所有对象的名称
*
* @param bucketName
* @return
* @throws Exception
*/
public static List<String> listObjects(String bucketName) throws Exception {
ListObjectsArgs args = ListObjectsArgs.builder()
.bucket(bucketName)
.build();
Iterable<Result<Item>> objects = minioClient.listObjects(args);
List<String> objectNames = new ArrayList<>();
for (Result<Item> result : objects) {
objectNames.add(result.get().objectName());
}
return objectNames;
}
/**
* 下载文件
*
* @param bucketName: 桶名
* @param url: 文件访问地址
* @param response:
* @return: void
*/
@SneakyThrows(Exception.class)
public static void download(String bucketName, String url, HttpServletResponse response) {
String objectName = urlAnalyze(url);
// 获取对象的元数据
final ObjectStat stat = minioClient.statObject(bucketName, urlAnalyze(url));
response.setContentType(stat.contentType());
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(objectName, "UTF-8"));
InputStream is = minioClient.getObject(bucketName, objectName);
is.close();
}
/**
* 获取minio文件的下载地址
*
* @param bucketName: 桶名
* @param objectName: 文件名
* @return: java.lang.String
*/
@SneakyThrows(Exception.class)
public static String getFileUrl(String bucketName, String objectName) {
return minioClient.presignedGetObject(bucketName, objectName);
}
/**
* @param bucketName 桶名
* @param folderName 文件夹名称
* @param file 文件
* @throws InvalidKeyException
* @throws ErrorResponseException
* @throws IllegalArgumentException
* @throws InsufficientDataException
* @throws InternalException
* @throws InvalidBucketNameException
* @throws InvalidResponseException
* @throws NoSuchAlgorithmException
* @throws XmlParserException
* @throws IOException
* @throws ServerException
*/
public static void putObject(String bucketName, String folderName, String newFileName, MultipartFile file)
throws InvalidKeyException, ErrorResponseException, IllegalArgumentException, InsufficientDataException,
InternalException, InvalidBucketNameException, InvalidResponseException, NoSuchAlgorithmException,
XmlParserException, IOException, ServerException {
//判断桶是否存在
boolean flag = bucketExists(bucketName);
if (flag) {
//王文建文件夹并上传文件
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(bucketName)
.object(folderName + "/" + newFileName)
.contentType(ViewContentType.getContentType(file.getOriginalFilename()))
.stream(file.getInputStream(), file.getSize(), -1)
.build();
minioClient.putObject(putObjectArgs);
}
}
public ObjectStat statObject(String bucketName, String objectName)
throws InvalidKeyException, ErrorResponseException, IllegalArgumentException, InsufficientDataException,
InternalException, InvalidBucketNameException, InvalidResponseException, NoSuchAlgorithmException,
XmlParserException, IOException {
boolean flag = bucketExists(bucketName);
if (flag) {
ObjectStat statObject = null;
try {
statObject = minioClient.statObject(bucketName, objectName);
} catch (ServerException e) {
e.printStackTrace();
}
return statObject;
}
return null;
}
/**
* 创建文件夹
*
* @param bucketName
* @param folderName
* @return
* @throws IOException
* @throws InvalidKeyException
* @throws InvalidResponseException
* @throws InsufficientDataException
* @throws NoSuchAlgorithmException
* @throws ServerException
* @throws InternalException
* @throws XmlParserException
* @throws InvalidBucketNameException
* @throws ErrorResponseException
*/
public static void createFolder(String bucketName, String folderName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, InvalidBucketNameException, ErrorResponseException {
// 创建虚拟文件夹
String objectName = folderName + "/";
// 使用空的输入流创建对象
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(new ByteArrayInputStream(new byte[0]), 0, -1)
.build());
}
支持上传文件、下载、访问文件、预签名底子(有效期地址)、对桶的操作
配置类SiMinIoProperties
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class SiMinIoProperties {
/**
* minio地址+端口号
*/
private String endpoint;
/**
* minio用户名
*/
private String accessKey;
/**
* minio密码
*/
private String secretKey;
/**
* 文件桶的名称
*/
private String bucketName;
/**
* 访问图片有效时间(单位:秒)
*/
private Integer expiresInSeconds;
}
这里配置在yml配置文件上
注意:minio的用户名和密码,也就是秘钥,在minio控制台获取,需要获取秘钥教程,请前往下面链接地址
https://www.cnblogs.com/ckfeng/p/17779307.html
桶要设置访问权限为public,不然无法访问!
枚举类ViewContentType
DEFAULT("default","application/octet-stream"),
JPG("jpg", "image/jpeg"),
TIFF("tiff", "image/tiff"),
GIF("gif", "image/gif"),
JFIF("jfif", "image/jpeg"),
PNG("png", "image/png"),
TIF("tif", "image/tiff"),
ICO("ico", "image/x-icon"),
JPEG("jpeg", "image/jpeg"),
WBMP("wbmp", "image/vnd.wap.wbmp"),
FAX("fax", "image/fax"),
NET("net", "image/pnetvue"),
JPE("jpe", "image/jpeg"),
RP("rp", "image/vnd.rn-realpix"),
MAP("mp4", "video/mp4"),
MPEG("mpeg", "video/mpeg"),
AVI("avi", "video/avi"),
PDF("pdf", "application/pdf")
;
private String prefix;
private String type;
public static String getContentType(String prefix){
if(StringUtils.isEmpty(prefix)){
return DEFAULT.getType();
}
prefix = prefix.substring(prefix.lastIndexOf(".") + 1);
for (ViewContentType value : ViewContentType.values()) {
if(prefix.equalsIgnoreCase(value.getPrefix())){
return value.getType();
}
}
return DEFAULT.getType();
}
ViewContentType(String prefix, String type) {
this.prefix = prefix;
this.type = type;
}
public String getPrefix() {
return prefix;
}
public String getType() {
return type;
}
有其它问题请下方留言