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

目标: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);
    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值