Java SpringBoot批量获取Minio中多个文件进行压缩成zip下载

FileController 接口请求为Post

java 复制代码
@RestController
@RequestMapping("/file")
@Api(tags = "file文件操作")
public class FileController {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileController.class);

    @Autowired
    private IFileService fileService;
    @ApiOperation(value = "下载压缩文件Zip", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    @RequestMapping(value = "/downZipFile", produces = "application/octet-stream", method = RequestMethod.POST)
    public void downZipFile(@RequestBody ZipFileDto zipFileDto, HttpServletResponse response) {
        try {
            fileService.downZipFile(zipFileDto, response);
        } catch (Exception e) {
            new CommonResult().failed(e.getMessage());
        }
    }
}

ZipFileDto.java 入参实体类

java 复制代码
@Data
public class ZipFileDto {
    /**
     * 文件名称.zip
     */
    private String downName;

    private List<fileListDto> fileList;

    @Data
    public static class fileListDto {
        /**
         * 下载文件名称
         */
        private String fileName;
        /**
         * 下载文件路径
         */
        private String filePath;
    }
}

IFileService.java 接口层

java 复制代码
public interface IFileService {

    void downZipFile(ZipFileDto zipFileDto, HttpServletResponse response) throws Exception;

}

MinioFileServiceImpl.java 实现类

java 复制代码
@Service
public class MinioFileServiceImpl implements IFileService {

	private static final Logger LOGGER = LoggerFactory.getLogger(MinioFileServiceImpl.class);
	@Value("${minio.storageClass}")
	private String STORAGECLASS; //存储类型
	@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; //密码

	@Override
	public void downZipFile(ZipFileDto zipFileDto, HttpServletResponse response) throws Exception {
		try {
			// 获取minio中多个文件进行压缩成zip下载
			InputStream fis;
			MinioClient minioClient = new MinioClient(ENDPOINT, ACCESS_KEY, SECRET_KEY);
			String bucketName = BUCKET_NAME;
			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
			try (ZipOutputStream zos = new ZipOutputStream(byteArrayOutputStream)) {
				for (ZipFileDto.fileListDto fileListDto : makeUnique(zipFileDto.getFileList())) {
					String filePath = StringUtils.substringAfter(fileListDto.getFilePath(), "/mall");
					try (InputStream is = minioClient.getObject(bucketName, filePath)) {
						zos.putNextEntry(new ZipEntry(fileListDto.getFileName()));
						byte[] buffer = new byte[1024];
						int len;
						while ((len = is.read(buffer)) > 0) {
							zos.write(buffer, 0, len);
						}
						zos.closeEntry();
					}
				}
			} catch (NoSuchAlgorithmException e) {
				throw new RuntimeException(e);
			} catch (InvalidKeyException e) {
				throw new RuntimeException(e);
			}
			// 从 ByteArrayOutputStream 获取字节数组
			byte[] zipData = byteArrayOutputStream.toByteArray();
			ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(zipData);
			fis = new BufferedInputStream(byteArrayInputStream);
			byte[] buffer = new byte[fis.available()];
			fis.read(buffer);
			fis.close();
			response.reset();
			// 设置response的Header
			response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(zipFileDto.getDownName(), "UTF-8"));
			OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
			response.setContentType("application/octet-stream;charset=UTF-8");
			toClient.write(buffer);
			toClient.flush();
			toClient.close();
		} catch (MinioException | IOException e) {
			e.printStackTrace();
			LOGGER.error(e.getMessage());
		}
	}


	public static List<ZipFileDto.fileListDto> makeUnique(List<ZipFileDto.fileListDto> fileListDtos) {
		Map<String, Integer> nameCount = new HashMap<>();
		List<ZipFileDto.fileListDto> uniqueNames = new ArrayList<>();
		fileListDtos.forEach(t->{
			ZipFileDto.fileListDto fileListDto=new ZipFileDto.fileListDto();
			String str = t.getFileName();
			int lastIndex = str.lastIndexOf(".");
			String suffix = str.substring(lastIndex + 1);
			String name = str.substring(0,lastIndex);
			if (nameCount.containsKey(name)) {
				nameCount.put(name, nameCount.get(name) + 1);
				fileListDto.setFilePath(t.getFilePath());
				fileListDto.setFileName(name + "(" + nameCount.get(name) + ")."+suffix);
				uniqueNames.add(fileListDto);
			} else {
				nameCount.put(name, 1);
				fileListDto.setFilePath(t.getFilePath());
				fileListDto.setFileName(name+"."+suffix);
				uniqueNames.add(fileListDto);
			}
		});
		return uniqueNames;
	}
}

项目yml配置

XML 复制代码
minio:
  storageClass: minio  # nfs/minio
  accessKey: minioadmin
  bucketName: mall
  endpoint: http://10.110.xx.xx:9000
  secretKey: minioadmin

下载后就是这样的

相关推荐
小法师爱分享3 分钟前
StickyNotes,简单便签超实用
java·python
qq_297574674 分钟前
Linux 服务器 Java 开发环境搭建保姆级教程
java·linux·服务器
金牌归来发现妻女流落街头16 分钟前
【从SpringBoot到SpringCloud】
java·spring boot·spring cloud
毅炼16 分钟前
Java 基础常见问题总结(4)
java·后端
无小道17 分钟前
Qt——事件简单介绍
开发语言·前端·qt
devmoon22 分钟前
在 Paseo 测试网上获取 Coretime:On-demand 与 Bulk 的完整实操指南
开发语言·web3·区块链·测试用例·智能合约·solidity
GR23423428 分钟前
2025年影视仓TV+手机官方版 内置地址源支持高清直播
java·智能手机·软件
皮卡丘不断更30 分钟前
手搓本地 RAG:我用 Python 和 Spring Boot 给 AI 装上了“实时代码监控”
人工智能·spring boot·python·ai编程
kylezhao201940 分钟前
C# 中的 SOLID 五大设计原则
开发语言·c#
程序员清风1 小时前
北京回长沙了,简单谈谈感受!
java·后端·面试