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

news2024/11/24 13:41:29

目标: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 {

    @Resource
    private OSSClient ossClient;

    @Resource
    private ImageService imageService;


    @Override
    public ZipFileUploadData uploadImgZip(MultipartFile file) {
        Stopwatch stopwatch = Stopwatch.createStarted();
        QMonitor.recordOne("ZipServiceImpl.uploadImgZip.total");
        if (file.isEmpty() || file.getContentType() == null) {
            throw new BusinessException("文件不能为空");
        }
        // 判断文件类型是否为zip
        if (!file.getContentType().equals("application/zip")) {
            throw new BusinessException("上传文件类型错误,请上传zip文件");
        }
        ZipFileUploadData zipFileUploadData = new ZipFileUploadData();
        List<String> imageUrls = new ArrayList<>();

        // 解压zip
        try (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.coloradmin.cn/o/2127671.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

KTV 营业明细+员工提成—SAAS本地化及未来之窗行业应用跨平台架构

一、ktv 绩效必要性 1. 激励员工积极性&#xff1a;提成制度能够直接将员工的努力和收入挂钩&#xff0c;促使员工更加积极主动地工作&#xff0c;以获取更高的收入。 2. 提高工作效率和业绩&#xff1a;为了获得更多提成&#xff0c;员工会努力提高工作效率&#xff0c;增加业…

别中招!从“超低利率“到“包过承诺“,揭秘贷款几大陷阱!

今天咱们聊聊贷款时得防的那些坑&#xff0c;免得一不小心就被套路了。你以为找了个靠谱帮手&#xff0c;结果却是步步陷阱&#xff0c;咱们一起来揭秘这些招数&#xff0c;也给大伙儿提个醒。 第一招&#xff0c;低利率诱惑。正常普通信用贷款服务费是2-15%个点内&#xff0c;…

第十七节:学习Hutool上传文件(自学Spring boot 3.x的第四天)

这节记录下如何使用Hutool库上传本地的文件到服务器端&#xff08;因为是练习&#xff0c;所以是本地端&#xff09;。 第一步&#xff1a;引入Hutool库最新版本&#xff0c;通过maven方式。&#xff08;最新版本需去maven仓库查询&#xff09; 第二步&#xff1a;编写一个post…

Django路由访问及查询数据

1、在应用模块下&#xff0c;创建urls文件&#xff0c;用来存放访问路由 2、在项目总访问url里面注册路由 3、在view文件里&#xff0c;定义方法参数 from django.core import serializers from django.db import connection from django.http import HttpResponse, JsonRespo…

【佳学基因检测】在织梦网站中, 创建或修改目录:/var/www/html/cp 失败! DedeTag Engine Create File False

【佳学基因检测】在织梦网站中, 创建或修改目录&#xff1a;/var/www/html/cp 失败&#xff01; DedeTag Engine Create File False 在使用 DedeCMS&#xff08;一个常用的内容管理系统&#xff09;时&#xff0c;如果遇到“创建或修改目录&#xff1a;/var/www/html/cp 失败&…

背靠大众,「半价Model 3」卖爆,小鹏走出低谷

‍作者 |老缅 编辑 |德新 各路消息都在显示&#xff0c;小鹏MONA M03爆单了。 总裁王凤英在庆功宴上喝下了人生第一杯酒。 小鹏MONA产品线负责人透露&#xff0c;上市后的两天内&#xff0c;MONA全国的试驾车累计开了超过10万公里。 在上市后的48小时内&#xff0c;M03获得…

华为OD机试 - 周末爬山 - 广度优先搜索BFS(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

Mysql基础——DML

数据操作语言&#xff08;DML&#xff0c;Data Manipulation Language&#xff09; DML语句用于对数据库中的数据进行操作&#xff08;增删改查数据&#xff09;&#xff0c;主要包括&#xff1a; INSERT&#xff1a;向表中插入数据&#xff0c;例如 INSERT INTO table_name …

超简单,3步训练Flux Lora模型,附整合包!

超简单&#xff0c;3步训练Flux Lora模型&#xff0c;附整合包&#xff01; &#x1f389; 12G显存也能炼Flux Lora模型&#xff1f;&#xff01;3步速成&#xff0c;小白也能轻松上手&#xff01; 兄弟们&#xff01;AI绘画领域又迎来了一波革命&#xff01;Flux Lora模型训练…

2024中国500强企业高峰论坛安然大健康分论坛圆满举办!

一场巅峰聚首的风云际会&#xff0c;一次引领未来的行业盛宴。 9月10日至11日&#xff0c;由中国企业联合会、中国企业家协会主办的2024中国500强企业高峰论坛在天津举行&#xff0c;本届高峰论坛以“向‘新’而行、打造更多世界一流企业”为主题&#xff0c;汇集业内知名企业…

利用AI驱动智能BI数据可视化-深度评测Amazon Quicksight(三)

简介 随着生成式人工智能的兴起&#xff0c;传统的 BI 报表功能已经无法满足用户对于自动化和智能化的需求&#xff0c;今天我们将介绍亚马逊云科技平台上的AI驱动数据可视化神器 – Quicksight&#xff0c;利用生成式AI的能力来加速业务决策&#xff0c;从而提高业务生产力。…

【Qt应用】Qt编写简易登录注册界面

目录 引言 一、准备工作 二、设计思路 2.1 登录 2.2 注册 三、登录功能 3.1 创建账号与密码输入框 3.2 设置密码输入框格式 3.2.1 初始 3.2.2 创建一个显示隐藏按钮 3.2.3 信号与槽函数 3.3 创建登录按钮 3.4 创建可选功能 四、注册功能 4.1 账号和密码输入…

【Go】深入探索Go语言中运算符

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

路基边坡自动化监测解决方案

物联网云平台 平台登录--用户登录 输入网址&#xff1a;http://yun.sj2000.org.cn&#xff0c;进入系统登录界面&#xff0c;输入用户名及密码后进入系统平台。 设备详情--设备概览 登录系统平台后&#xff0c;用户可在界面左侧看到系统项目栏和子项目选项&#xff0c;登陆的…

【Python爬虫系列】_018.多线程与多进程

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈 入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈 虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈 PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈 Oracle数…

3. 进阶指南:自定义 Prompt 提升大模型解题能力

怎么判断 Prompt 的好坏&#xff0c;有什么问题有着标准答案么&#xff1f; 答&#xff1a;让大模型求解数学问题。 李宏毅老师的 HW4 正好提到了有关数学问题的 Prompt&#xff0c;所以我决定中间插一篇这样的文章。通过本文你将&#xff1a; 了解各种 Prompt 如何影响大型语言…

基于asp.net电子邮件系统设计与实现

1 引言 1&#xff0e;1 电子邮件介绍 电子邮件(简称E-mai1)又称电子信箱、电子邮政&#xff0c;它是—种用电子手段提供信息交换的通信方式。它是全球多种网络上使用最普遍的一项服务。这种非交互式的通信,加速了信息的交流及数据传送,它是—个简易、快速的方法。通过连接全…

个人用户如何有效利用固态硬盘数据恢复工具

固态硬盘相较于机械硬盘来说更为小巧&#xff0c;所以很多人选择使用固态硬盘来进行数据的存储。这些存储设备都可能会遇到一些意外导致的数据丢失情况。好在现在的科技比较发达&#xff0c;这次我们来聊一聊有哪些固态硬盘数据恢复工具可以解决这个问题吧。 1.福晰数据恢复 …

Sentinel 高级

一、请求限流 1.介绍 处理并发量大时资源耗尽问题 Sentinel的请求限流功能主要体现在对QPS&#xff08;每秒查询率&#xff09;和线程数的控制上。当某个API接口或服务的请求量达到设定的QPS阈值时&#xff0c;Sentinel会触发限流规则&#xff0c;对这些超出阈值的请求进行限…

Selenium自动化测试面试题合集!

1、什么是自动化测试、自动化测试的优势是什么&#xff1f; 通过工具或脚本代替手工测试执行过程的测试都叫自动化测试。 自动化测试的优势&#xff1a; 1、减少回归测试成本 2、减少兼容性测试成本 3、提高测试反馈速度 4、提高测试覆盖率 5、让测试工程师做更有意义的…