Minio文件操作

原创
2024/12/24 15:37
阅读数 11

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)
  })
}

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部