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

news/2024/10/4 20:42:37/文章来源:https://blog.csdn.net/Alice_qixin/article/details/142143187

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

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

MacOs会多出来

以及本身一个文件夹

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

要知道

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

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

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.ldbm.cn/p/441367.html

如若内容造成侵权/违法违规/事实不符,请联系编程新知网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

若依搭建vue3项目

搭建vue3后台管理系统页面&#xff0c;与vue2基本一致&#xff0c;方便以后可以快速搭建&#xff0c;现在将基础搭建以及若依框架搭建流程再次梳理一下 文章目录 环境准备1. Node.js环境安装2. 推荐包管理器&#xff1a;pnpm3. 安装create-vue工具 方式一&#xff1a;脚手架搭建…

基于 onsemi NCV78343 NCV78964的汽车矩阵式大灯方案

一、方案描述 大联大世平集团针对汽车矩阵大灯&#xff0c;推出 基于 onsemi NCV78343 & NCV78964的汽车矩阵式大灯方案。 开发板搭载的主要器件有 onsemi 的 Matrix Controller NCV78343、LED Driver NCV78964、Motor Driver NCV70517、以及 NXP 的 MCU S32K344。 二、开…

MyBatis-Plus 与 Mockito:解决 Lambda 缓存初始化问题

问题背景 MyBatis-Plus 提供了便捷的 Lambda 查询表达式&#xff0c;但它依赖于实体类与数据库表的映射缓存。如果在测试环境中&#xff0c;这些映射未正确初始化&#xff0c;可能导致 can not find lambda cache for this entity 异常。这一问题特别容易在与 Mockito 搭配使用…

甘特图组件DHTMLX Gantt中文教程 - 如何实现持久UI状态

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求&#xff0c;是最完善的甘特图图表库。 在现代Web应用程序中&#xff0c;在页面重新加载之间保持UI元素的状态对于流畅的用户体验至关重要。 在本教程中我们将知道您完成…

木材裂纹检测系统源码分享

木材裂纹检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(五)

概述 在 WWDC 24 中,苹果推出了数据库框架 SwiftData 2.0 版本。其新加入的历史记录追踪(History Trace)机制着实让秃头码农们“如痴如醉”了一番。 我们在之前的博文中已经介绍了 History Trace 是如何处理数据新增操作的。而在这里,我们将再接再厉来完成数据删除时的全盘…

C++核心编程和桌面应用开发 第一天

目录 1.C的编程方式 2.双冒号::运算符 3.命名空间 3.1作用 3.2命名空间内的东西 3.3注意事项 4.using的用法 4.1using的声明 4.2using编译指令 5.C相较于C的增强 5.1全局变量检测增强 5.2函数检测增强 5.3类型转换检测增强 5.4结构体增强 5.5三目运算符增强 5.…

卷积神经网络-经典分类网络结构(LetNet-5,AlexNet)

目录 一&#xff1a;LeNet-5解析 1.网络结构 输入层&#xff1a; 1.conv1&#xff1a; 2.pool1层&#xff1a; 3.conv2&#xff1a; 4.pool2&#xff1a; 5.fc3&#xff0c;fc4&#xff1a; 6.output层: 2.参数形状 二&#xff1a;AlexNet 1层&#xff1a; 2层&am…

Element UI:初步探索 Vue.js 的高效 UI 框架

Element UI&#xff1a;初步探索 Vue.js 的高效 UI 框架 一 . ElementUI 基本使用1.1 Element 介绍1.2 Element 快速入门1.3 基础布局1.4 容器布局1.5 表单组件1.6 表格组件1.6.1 基础表格1.6.2 带斑马纹表格1.6.3 带边框表格1.6.4 带状态的表格 1.7 导航栏组件讲解 二 . 学生列…

可提示 3D 分割研究里程碑!SAM2Point:SAM2加持泛化任意3D场景、任意提示!

郑重声明&#xff1a;本解读已获得论文作者的原创解读授权 文章链接&#xff1a;https://arxiv.org/pdf/2408.16768 在线demo: https://huggingface.co/spaces/ZiyuG/SAM2Point code链接&#xff1a;https://github.com/ZiyuGuo99/SAM2Point 亮点直击 无投影 3D 分割&#xff1…

汽车无钥匙启动功能工作原理

移‌动管家无钥匙启动‌是一种科技化的汽车启动方式&#xff0c;它允许车主在不使用传统钥匙的情况下启动车辆。这种技术通过智能感应系统实现&#xff0c;车主只需携带智能钥匙&#xff0c;当靠近车辆时&#xff0c;车辆能够自动解锁并准备启动。启动车辆时&#xff0c;车主无…

828华为云征文 | 基于Docker与Jenkins实现自动化部署

前言 重塑自动化部署新高度&#xff0c;Docker携手Jenkins&#xff0c;在华为云Flexus X云服务器的加持下&#xff0c;引领持续集成与部署的新纪元。Flexus X以其卓越的性能、灵活的资源配置和高效的成本优化&#xff0c;为Docker容器化应用与Jenkins自动化流水线提供了理想的运…

在广袤的数据通信旷野,“伙伴+华为”体系点亮星云

在浩浩荡荡的智能化变革中&#xff0c;从用户层面看&#xff0c;来自地市区县的各个行业与企业是真正的主体&#xff0c;以他们为主体的商业市场&#xff0c;提供了智能化进程中最为关键的广度。 而从技术角度看&#xff0c;数据通信是千行万业都需要的基本数字化能力。数据通信…

QGIS 如何连接空间库,并实时编辑空间表?编辑后库表如何刷新,保证是最新数据?

文章目录 一、什么是 qgis&#xff1f;二、qgis 如何连接数据库三、实时编辑空间表四、编辑后库表如何刷新&#xff0c;保证是最新数据&#xff1f;五、总结 一、什么是 qgis&#xff1f; QGIS&#xff08;原称Quantum GIS&#xff09;是一个用户界面友好的开源桌面端软件&…

ES-Search API

一、Search API的分类 URI Search 在url中传入查询参数进行查询&#xff0c;Request Body Search 使用es提供的&#xff0c;基于json的更加完备的Query Domain Specific Language(DSL) 语法范围/_search集群上所有的索引/index1/_search查询索引名为index1的索引/index1,inde…

N-152基于java贪吃蛇游戏5

开发工具eclipse,jdk1.8 文档截图&#xff1a; N-152基于java贪吃蛇游戏5

JavaScript ES6特性(var let const、function=>、增强表达赋值、类与对象)

一、var let const 1、var var明明定义在for里面的但是外部能够访问这个变量,说明var可以跨域访问。 2、let let明明定义在for里面的但是外部不能够访问这个变量,说明let不可以跨域访问。 3、const const foo = {}; // 为 foo 添加一个属性,可以成功 foo.prop = 123; fo…

影刀RPA实战:自动化批量生成条形码完整指南

今天我们聊聊使用影刀来实现批量生成条形码&#xff0c;条形码在零售行业运用非常广泛&#xff0c;主要作用表现在产品识别&#xff0c;库存管理&#xff0c;销售管理&#xff0c;防伪保护等&#xff0c;这些作用使其成为现代商业和工业环境中不可或缺的工具&#xff0c;它极大…

大数据-132 - Flink SQL 基本介绍 与 HelloWorld案例

Flink SQL Flink SQL 是 Apache Flink 提供的一种高层次的查询语言接口&#xff0c;它基于 SQL 标准&#xff0c;为开发者提供了处理流式数据和批处理数据的能力。Flink SQL 允许用户使用标准 SQL 查询语言在数据流和数据表上执行复杂的操作&#xff0c;适用于多种应用场景&am…

MongoDB创建用户教程

1、连接到 MongoDB 首先&#xff0c;打开你的终端并使用 mongosh 命令连接到 MongoDB 服务器&#xff1a; mongosh --host <hostname> --port <port> 说明&#xff1a; mongosh&#xff1a;启动 MongoDB Shell 命令行工具。 --host <hostname>&#xff1a…