JAVA实现压缩包解压兼容Windows系统和MacOs

embedded/2024/12/23 4:20:54/

目标:JAVA实现压缩包解压获取图片素材

问题:Windows系统和MacOs压缩出来的zip内容有区别

MacOs会多出来

以及本身一个文件夹

windows则不会。为了解决这个问题。兼容mac的压缩包增加一层过滤

要知道

ZipInputStream 可以读取 ZIP 文件中的条目,包括文件和文件夹。当使用 ZipInputStream 遍历 ZIP 文件时,它会按照 ZIP 文件中的顺序返回每个条目,包括嵌套在文件夹内的文件

所以,只要过滤掉文件夹以及"__MACOSX/"开头的文件,就可以取到所有正常的图片了。

java">import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;import javax.annotation.Resource;import lombok.extern.slf4j.Slf4j;
import qunar.tc.oss.OSSClient;
import qunar.tc.oss.PutObjectResponse;/*** zip服务*/
@Service
@Slf4j
public class ZipServiceImpl implements ZipService {@Resourceprivate OSSClient ossClient;@Resourceprivate ImageService imageService;@Overridepublic ZipFileUploadData uploadImgZip(MultipartFile file) {Stopwatch stopwatch = Stopwatch.createStarted();QMonitor.recordOne("ZipServiceImpl.uploadImgZip.total");if (file.isEmpty() || file.getContentType() == null) {throw new BusinessException("文件不能为空");}// 判断文件类型是否为zipif (!file.getContentType().equals("application/zip")) {throw new BusinessException("上传文件类型错误,请上传zip文件");}ZipFileUploadData zipFileUploadData = new ZipFileUploadData();List<String> imageUrls = new ArrayList<>();// 解压ziptry (ZipInputStream zis = new ZipInputStream(file.getInputStream(), Charset.forName("GBK"))) {ZipEntry zipEntry;int index = 1;while ((zipEntry = zis.getNextEntry()) != null) {//判断是否为文件夹(此处为了兼容macos系统压缩包,过滤MACOSX文件夹素材以及文件夹)if (zipEntry.getName().startsWith("__MACOSX/") || zipEntry.isDirectory()) {zis.closeEntry();continue;}// 处理图片文件if (isImageFile(zipEntry.getName())) {String imageUrl = processImageFile(zis, index);if (imageUrl.isEmpty()) {log.error("压缩包内图片上传失败");throw new BusinessException("压缩包内图片上传失败");}imageUrls.add(imageUrl);} else {// 处理非图片文件,抛出异常log.error("压缩包内上传文件类型错误,请上传图片文件");throw new BusinessException("压缩包内上传文件类型错误,请上传图片文件");}zis.closeEntry();  // 确保在处理完每个条目后关闭index++;}// 判断是否解析得到了图片列表if (CollectionUtils.isEmpty(imageUrls)) {log.error("压缩包内图片图片上传失败");throw new BusinessException("压缩包内图片图片上传失败");}zipFileUploadData.setNumIconInfo(imageUrls);PutObjectResponse putObjectResponse = getZipUploadUrl(file);if (putObjectResponse == null || putObjectResponse.getUrl().isEmpty()) {log.error("压缩包上传失败");throw new BusinessException("压缩包上传失败");}zipFileUploadData.setZipUrl(putObjectResponse.getUrl());} catch (IOException e) {log.error("读取ZIP文件时发生错误", e);throw new BusinessException("读取ZIP文件时发生错误");} catch (Exception e) {log.error("上传zip压缩包处理发生错误", e);throw new BusinessException(e.getMessage());} finally {QMonitor.recordQuantile("ZipServiceImpl.uploadImgZip.final", stopwatch.elapsed(TimeUnit.MILLISECONDS));}// 返回结果QMonitor.recordOne("ZipServiceImpl.uploadImgZip.success");return zipFileUploadData;}/*** 获取zip上传url* @param file 文件* @return PutObjectResponse 上传结果* @throws IOException IO异常*/private PutObjectResponse getZipUploadUrl(MultipartFile file) throws IOException {String extName = "";String originalFilename = file.getOriginalFilename();if (originalFilename != null && !originalFilename.isEmpty()) {extName = StringUtils.getFilenameExtension(originalFilename);}String fileName = String.format("zip-%s.%s", UUID.randomUUID().toString().replace("-", ""), extName);File tempFile = Files.createTempFile(null, fileName).toFile();file.transferTo(tempFile);PutObjectResponse response = ossClient.putObject(fileName, tempFile);// 确保上传后删除临时文件Files.delete(tempFile.toPath());return response;}private boolean isImageFile(String fileName) {// 这里可以添加更多的图片格式检查return fileName.toLowerCase().endsWith(".png") || fileName.toLowerCase().endsWith(".jpg") || fileName.toLowerCase().endsWith(".jpeg");}private String processImageFile(InputStream inputStream, int index) throws Exception {ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int length;while ((length = inputStream.read(buffer)) != -1) {baos.write(buffer, 0, length);}byte[] imageBytes = baos.toByteArray();String base64Image = Base64.getEncoder().encodeToString(imageBytes);String fileName = String.valueOf(index).concat(".png");return imageService.uploadImg(base64Image, fileName);}}


http://www.ppmy.cn/embedded/112081.html

相关文章

亚数TrustAsia亮相第十四届智慧城市与智能经济博览会,入围“2024数据要素创新应用优秀成果”!

智博会 2024年9月6日至8日&#xff0c;由宁波市人民政府、浙江省经济和信息化厅、中国信息通信研究院、中国电子信息行业联合会、中国电信、中国移动、中国联通主办的2024世界数字经济大会暨第十四届智慧城市与智能经济博览会&#xff08;以下简称“智博会”&#xff09;在宁波…

Http详解

代理 是 HTTP 协议中请求方和应答方中间的一个环节&#xff0c;作为“中转站”&#xff0c;既可以 转发客户端的请求&#xff0c;也可以转发服务器的应答。 ​ 代理有很多的种类&#xff0c;常见的有&#xff1a; 匿名代理&#xff1a;完全“隐匿”了被代理的机器&#xff0c…

深度学习时遇到tensor([0.], device=‘cuda:0‘)等输出

更改了数据集后进行训练遇到了以下输出&#xff0c;精度正常提升&#xff0c;训练正常&#xff0c;就是精度和map之间又很多输出&#xff0c;如下&#xff1a; tensor([0.], devicecuda:0), tensor([0.], devicecuda:0), tensor([0.], devicecuda:0), tensor([0.], devicecuda…

数据结构——(java版)Map与Set

文章目录 二叉搜索树&#xff08;1&#xff09; 二叉搜索树的概念&#xff1a;&#xff08;2&#xff09;二叉搜索树的意义&#xff1a;&#xff08;3&#xff09;二叉搜索树的实现&#xff1a;实现的方法与属性实现二叉搜索树的查询&#xff1a;实现二叉搜索树的插入&#xff…

leetcode01——27. 移除元素(双指针)、977. 有序数组的平方(双指针)、209. 长度最小的子数组(双指针/滑动窗口)

27. 移除元素 /** 定义快慢指针&#xff0c;均从0开始&#xff0c;fast向后移动&#xff0c;遇到不为删除值的就停下&#xff0c;将值赋值给slow,slow 遇到等于目标值就直接跳过&#xff0c;不等于目标值就赋值&#xff0c;这样就能 过滤掉&#xff08;也就是删除掉&#xff0…

重头开始嵌入式第四十一天(数据结构 树 哈希表)

树 目录 树 树的定义 二叉树&#xff0c;binary tree 特殊的二叉树 二叉树的特性 层序遍历 1.创建树CreateBiTree(); 2.销毁树DestroyBiTree(); 3.前序遍历void PreOrderTraverse(); 4.中序遍历void InOrderTraverse(BiTree T); 5.后序遍历void PostOrderTraverse(…

如何在Flask中实现用户认证

在Flask中实现用户认证通常涉及几个关键步骤&#xff1a;使用第三方库&#xff08;如Flask-Login或Flask-Security&#xff09;、用户数据管理、登录表单处理、会话管理以及保护需要认证的路由。以下是使用Flask-Login库实现用户认证的基本步骤&#xff1a; 1. 安装Flask-Logi…

Spring Boot集成Mockito快速入门Demo

1.什么是Mockito&#xff1f; Mockito是一个模拟测试框架&#xff0c;可以让你用优雅&#xff0c;简洁的接口写出漂亮的单元测试。Mockito可以让单元测试易于可读&#xff0c;产生简洁的校验错误。 使用场景 提前创建测试&#xff0c;TDD&#xff08;测试驱动开发&#xff0…