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