Minio配置文件
# 文件系统 (提供测试环境,不要乱传)
#minio:
#单机版
#url: http://***:9000/
#集群版内部地址,可以是局域网地址
#url: http://***:8000/
#互联网地址
#internet-url: https://www.***.com/***/
#access-key: ***
#secret-key: ***
minio:
url: http://***:8000/
internet-url: https://www.***.com/***/
access-key: ***
secret-key: ***
MinioTemplate.java
package com.dhcc.uam.common.minio.service;
import com.dhcc.uam.common.minio.vo.MinioItem;
import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.Result;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
/**
* minio 交互类
*
* @author dx
*/
@RequiredArgsConstructor
public class MinioTemplate implements InitializingBean {
private final String endpoint;
@Getter
private final String endpointInternet;
private final String accessKey;
private final String secretKey;
@Getter
private MinioClient client;
/**
* 创建bucket
*
* @param bucketName bucket名称
*/
@SneakyThrows
public void createBucket(String bucketName) {
if (!client.bucketExists(bucketName)) {
client.makeBucket(bucketName);
}
}
/**
* 获取全部bucket
* <p>
* https://docs.minio.io/cn/java-client-api-reference.html#listBuckets
*/
@SneakyThrows
public List<Bucket> getAllBuckets() {
return client.listBuckets();
}
/**
* @param bucketName bucket名称
*/
@SneakyThrows
public Optional<Bucket> getBucket(String bucketName) {
return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
}
/**
* @param bucketName bucket名称
*/
@SneakyThrows
public void removeBucket(String bucketName) {
client.removeBucket(bucketName);
}
/**
* 根据文件前置查询文件
*
* @param bucketName bucket名称
* @param prefix 前缀
* @param recursive 是否递归查询
* @return MinioItem 列表
*/
@SneakyThrows
public List<MinioItem> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
List<MinioItem> objectList = new ArrayList<>();
Iterable<Result<Item>> objectsIterator = client
.listObjects(bucketName, prefix, recursive);
Iterator<Result<Item>> iterator = objectsIterator.iterator();
while (iterator.hasNext()) {
objectList.add(new MinioItem(iterator.next().get()));
}
return objectList;
}
/**
* 获取文件外链
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param expires 过期时间 <=7
* @return url
*/
@SneakyThrows
public String getObjectURL(String bucketName, String objectName, Integer expires) {
String resUrl = "";
if(objectName != null && !"".equals(objectName)){
String url = this.client.presignedGetObject(bucketName,objectName, expires);
String[] urls = url.split("\\?");
if(urls.length>=2){
resUrl = urls[0];
}else{
resUrl = url;
}
resUrl = resUrl.replace(endpoint,endpointInternet);
}
return resUrl;
}
/**
* 获取文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @return 二进制流
*/
@SneakyThrows
public InputStream getObject(String bucketName, String objectName) {
return client.getObject(bucketName, objectName);
}
/**
* 上传文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
client.putObject(bucketName, objectName, stream, (long) stream.available(), null, null, "application/octet-stream");
}
/**
* 上传文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @param size 大小
* @param contextType 类型
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception {
client.putObject(bucketName, objectName, stream, size, null, null, contextType);
}
/**
* 获取文件信息
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
*/
public ObjectStat getObjectInfo(String bucketName, String objectName) throws Exception {
return client.statObject(bucketName, objectName);
}
/**
* 删除文件
*
* @param bucketName bucket名称
* @param objectName 文件名称
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeObject
*/
public void removeObject(String bucketName, String objectName) throws Exception {
client.removeObject(bucketName, objectName);
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.hasText(endpoint, "Minio url 为空");
Assert.hasText(accessKey, "Minio accessKey为空");
Assert.hasText(secretKey, "Minio secretKey为空");
this.client = new MinioClient(endpoint, accessKey, secretKey);
}
/**
* 根据文件路径得到预览文件绝对地址
*
* @param bucketName
* @param fileName 文件路径
* @return
*/
public String getPreviewFileUrl(String bucketName, String fileName) {
try {
String resUrl = "";
if(fileName != null && !"".equals(fileName)){
String url = this.client.presignedGetObject(bucketName,fileName);
String[] urls = url.split("\\?");
if(urls.length>=2){
resUrl = urls[0];
}else{
resUrl = url;
}
}
resUrl = resUrl.replace(endpoint,endpointInternet);
return resUrl;
}catch (Exception e){
e.printStackTrace();
return "";
}
}
public String getPreviewFileUrl2(String bucketName, String fileName) {
try {
String resUrl = "";
if(fileName != null && !"".equals(fileName)){
String url = this.client.getObjectUrl(bucketName,fileName);
String[] urls = url.split("\\?");
if(urls.length>=2){
resUrl = urls[0];
}else{
resUrl = url;
}
resUrl = resUrl.replace(endpoint,endpointInternet);
}
return resUrl;
}catch (Exception e){
e.printStackTrace();
return "";
}
}
/**
* 根据文件路径得到预览文件绝对地址
*
* @param bucketName
* @param imgurl 文件路径
* @return
*/
public String getPreviewFileUrlByurl(String bucketName, String imgurl) {
try {
if(imgurl != null && !"".equals(imgurl)){
String[] imgurls = imgurl.split("/");
String fileName = imgurls[imgurls.length-1];
String url = this.client.presignedGetObject(bucketName,fileName);
String[] urls = url.split("\\?");
if(urls.length>=2){
return urls[0];
}else{
return url;
}
}else{
return "";
}
}catch (Exception e){
e.printStackTrace();
return "";
}
}
}
上传文件
/**
* 上传文件
*
* @param file
* @return
*/
@Override
public Map uploadFile(MultipartFile file,String bucket_name) throws Exception {
String fileName = IdUtil.simpleUUID() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename());
Map<String, String> resultMap = new HashMap<>(4);
resultMap.put("bucketName",bucket_name);
resultMap.put("fileName", fileName);
resultMap.put("name", file.getOriginalFilename());
resultMap.put("url", String.format("/admin/sys-file/%s/%s", bucket_name, fileName));
resultMap.put("relativeUrl", String.format("/%s/%s", bucket_name, fileName));
resultMap.put("privateUrl", String.format("/admin/sys-file/%s/%s", bucket_name, fileName));
resultMap.put("publicUrl", String.format("%s/%s/%s", minioTemplate.getEndpointInternet(),bucket_name, fileName));
minioTemplate.putObject(bucket_name, fileName, file.getInputStream());
//文件管理数据记录,收集管理追踪文件
fileLog(file, fileName);
return resultMap ;
}
上传文件2
/**
* 上传文件
*
* @param file
* @return
*/
@Override
public Map uploadFile(MultipartFile file,String bucket_name,String conetentType) throws Exception {
String fileName = IdUtil.simpleUUID() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename());
Map<String, String> resultMap = new HashMap<>(4);
resultMap.put("bucketName",bucket_name);
resultMap.put("fileName", fileName);
resultMap.put("name", file.getOriginalFilename());
resultMap.put("url", String.format("/admin/sys-file/%s/%s", bucket_name, fileName));
resultMap.put("relativeUrl", String.format("/%s/%s", bucket_name, fileName));
resultMap.put("privateUrl", String.format("/admin/sys-file/%s/%s", bucket_name, fileName));
resultMap.put("publicUrl", String.format("%s/%s/%s", minioTemplate.getEndpointInternet(),bucket_name, fileName));
minioTemplate.putObject(bucket_name, fileName, file.getInputStream(),file.getInputStream().available(),conetentType);
//文件管理数据记录,收集管理追踪文件
fileLog(file, fileName);
return resultMap ;
}
文件下载
/**
* 读取文件
*
* @param bucket
* @param fileName
* @param response
*/
@Override
public void getFile(String bucket, String fileName, HttpServletResponse response) {
InputStream inputStream = null;
try{
inputStream = minioTemplate.getObject(bucket, fileName);
ObjectStat objectInfo = minioTemplate.getObjectInfo(bucket, fileName);
response.setContentType("application/octet-stream; charset=UTF-8");
response.addHeader("Content-Length", String.valueOf(objectInfo.length()));
IoUtil.copy(inputStream, response.getOutputStream());
} catch (Exception e) {
log.error("文件读取异常: {}", e.getMessage());
}finally {
if (inputStream !=null){
try {
inputStream.close();
//log.debug("{}","文件流已关闭");
} catch (IOException e) {
log.error("数据流关闭失败: {}",e.getMessage());
}
}
}
}
删除文件
/**
* 删除文件
*
* @param id
* @return
*/
@Override
@SneakyThrows
@Transactional(rollbackFor = Exception.class)
public Boolean deleteFile(Long id) {
SysFile file = this.getById(id);
minioTemplate.removeObject(CommonConstants.BUCKET_NAME, file.getFileName());
return this.removeById(id);
}
文件信息保存
/**
* 文件管理数据记录,收集管理追踪文件
*
* @param file 上传文件格式
* @param fileName 文件名
*/
private void fileLog(MultipartFile file, String fileName) {
SysFile sysFile = new SysFile();
//原文件名
String original = file.getOriginalFilename();
sysFile.setFileName(fileName);
sysFile.setOriginal(original);
sysFile.setFileSize(file.getSize());
sysFile.setType(FileUtil.extName(original));
sysFile.setBucketName(CommonConstants.BUCKET_NAME);
sysFile.setCreateUser(SecurityUtils.getUser()==null?"":SecurityUtils.getUser().getUsername());
this.save(sysFile);
}
获得预览路径
/**
* 根据文件路径得到预览文件绝对地址
*
* @param fileNmae
* @return
*/
@Override
public String getPreviewFileUrl(String bucketName, String fileNmae) {
return minioTemplate.getPreviewFileUrl( bucketName, fileNmae);
}
前端
/**
* <img> <a> src 处理
* @returns {PromiseLike<T | never> | Promise<T | never>}
*/
export function handleImg(url, id) {
return validatenull(url) ? null : request({
url: url,
method: 'get',
responseType: 'blob'
}).then((response) => { // 处理返回的文件流
const blob = response.data
const img = document.getElementById(id)
img.src = URL.createObjectURL(blob)
window.setTimeout(function() {
window.URL.revokeObjectURL(blob)
}, 0)
})
}
export function handleDown(filename, bucket) {
return request({
url: '/admin/sys-file/' + bucket + '/' + filename,
method: 'get',
responseType: 'blob'
}).then((response) => { // 处理返回的文件流
const blob = response.data
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = filename
document.body.appendChild(link)
link.click()
window.setTimeout(function() {
URL.revokeObjectURL(blob)
document.body.removeChild(link)
}, 0)
})
}