【已解决】Java zip解压时候 malformed input off : 4, length : 1
- 工作小总结
- 时间:2023-09-28 13:46
- 2273人已阅读
简介
Java zip解压时候 malformed 解决方案
🔔🔔🔔好消息!好消息!🔔🔔🔔
有需要的朋友👉:联系凯哥
需求:通过页面上传ZIP文件后,对zip文件进行解压。
遇到的错误:在进行zip解压的时候错误如下:
先看报错前的:
/** * 解压缩ZIP文件 * @param zipFile ZIP文件 * @param destDir 目标路径 */ public static void zipDecompress(File zipFile, File destDir) { byte[] buffer = new byte[1024]; try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) { ZipEntry entry = zis.getNextEntry(); if(!destDir.exists()){ destDir.mkdirs(); } while (entry != null) { File file = new File(destDir, entry.getName()); if (entry.isDirectory()) { file.mkdirs(); } else { File parent = file.getParentFile(); if (!parent.exists()) { parent.mkdirs(); } try (FileOutputStream fos = new FileOutputStream(file)) { int len; while ((len = zis.read(buffer)) > 0) { fos.write(buffer, 0, len); } } } entry = zis.getNextEntry(); } } catch (IOException e) { e.printStackTrace(); } }
分析原因:
然后查询后得到:
解决方案:
所以修改代码,在生产ZipInputStream时候添加编码:
扩展:
这个功能涉及到的知识点:
web的文件上传
将上传文件上传到服务器上
对zip文件进行解压
一、web文件上传:
@RequestMapping("/create-picture") public ResponseResult<String> createPicture(@RequestParam(value = "file") MultipartFile zipFile){ createPictureReportingThread.startCreateDataReport(param,zipFile); return ResponseResult.success("请等待五分钟后,在报告列表中查询"); }
二、将上传的文件上传到服务器上
public void makePictureReport( MultipartFile MultipartZipFile) { InputStream fis = null; try { String originalFileName = MultipartZipFile.getOriginalFilename(); String extendFileName = originalFileName.substring( originalFileName.lastIndexOf('.')); System.out.println("extendFileName:"+extendFileName); //校验是否为ZIP //生成新的文件名称 String saveFileName = UUID.randomUUID().toString().replace("-",""); String relativeFileDir = DateUtil.format(new Date(), "yyyyMMddHHmmSSS")+ File.separator+ saveFileName ; //上传文件 String fileBasePath = baseFileDir+relativeFileDir; FileUtils.uploadFile(MultipartZipFile,fileBasePath , saveFileName+extendFileName); //解压zip文件 String decompressPath = fileBasePath+ File.separator+ "decompress"+ File.separator; File zipFile = new File(fileBasePath+File.separator+ saveFileName+extendFileName); File decompressFile = new File(decompressPath); ZipUtils.zipDecompress(zipFile ,decompressFile); } catch (Exception e) { throw new RuntimeException(e); } }
其中的FileUtils:
@Slf4j public class FileUtils { /** * 上传文件 * @param file 文件 * @param filepath 保存路径 * @param filename 文件名称 */ public static String uploadFile(MultipartFile file, String filepath, String filename) throws Exception { if (ObjectUtils.isEmpty(file)) { log.info("文件为空"); return null; } File descFile = new File(filepath,filename); log.info("上传文件到"+descFile.getAbsolutePath()); //父目录不存在则建立相关文件夹 if(!descFile.getParentFile().exists()){ descFile.getParentFile().mkdirs(); } if (!descFile.exists()) { descFile.createNewFile(); } // 文件保存 try(InputStream source = file.getInputStream()) { org.apache.commons.io.FileUtils.copyInputStreamToFile(source,descFile); } catch (Exception e) { log.info("文件保存出现异常"); e.printStackTrace(); throw new BusinessException(-200,"文件保存出现异常"); } log.info("文件上传成功"); return descFile.getCanonicalPath(); } }
三、ZIP文件解压
ZipUtils代码类:
import java.io.*; import java.nio.charset.Charset; import java.nio.file.attribute.FileTime; import java.time.Instant; import java.util.Arrays; import java.util.Objects; import java.util.zip.Deflater; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; /** * @BelongsProject: kaigejava * @BelongsPackage: com.kaigejava.util * @Author: kaigejava * @CreateTime: 2023-09-28 10:33 * @Description: zip的工具类 * @Version: 1.0 */ public class ZipUtils { /** * 压缩文件(支持单个文件和单个文件夹) * @param sourceFile 被压缩文件/文件夹 * @param zipFile Zip文件 */ public static void zipCompress(File sourceFile, File zipFile) { try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))) { // 设置压缩方法 zos.setMethod(ZipOutputStream.DEFLATED); zos.setLevel(Deflater.BEST_COMPRESSION); // 默认为-1,压缩级别,1速度快,效率低,9 速度满,效率高 // zos.setLevel(Deflater.BEST_SPEED); zos.setComment("zip文件说明"); // 处理文件夹 if (sourceFile.exists() && sourceFile.isDirectory() && Objects.nonNull(sourceFile.listFiles())){ Arrays.stream(Objects.requireNonNull(sourceFile.listFiles())).forEach(file -> { addZipFile(file, zos); }); }else{ addZipFile(sourceFile, zos); } } catch (IOException e) { e.printStackTrace(); } } /** * 向ZIP中添加文件 * @param file 源文件 * @param zos zip输出流 */ private static void addZipFile(File file, ZipOutputStream zos){ if (!file.exists() || file.isDirectory()){ throw new RuntimeException("文件不存在或该文件为文件夹,请检查"); } try { // 读入文件 FileInputStream fis = new FileInputStream(file); // 创建压缩对象并设置一些属性 ZipEntry entry = new ZipEntry(file.getName()); entry.setMethod(ZipEntry.DEFLATED); // 压缩方法默认为DEFLATED // entry.setMethod(ZipEntry.STORED); // STORED(不压缩)。当使用STORED压缩方法时,需要设置未压缩的数据大小和CRC-32校验和,否则压缩和解压缩时会出现错误。 entry.setSize(file.length()); // 设置未压缩的数据大小,这里设置的是文件大小 // 计算 CRC-32 校验码 // byte[] data = Files.readAllBytes(file.toPath()); // CRC32 crc = new CRC32(); // crc.update(data); // entry.setCrc(crc.getValue()); // 设置CRC-32校验和,用于保证压缩后的数据完整性,尽量别手动设置,可以通过CRC-32计算 entry.setCompressedSize(file.length()); // 设置压缩后的数据大小,这里设置的是使用DEFLATED方法压缩后的数据大小 entry.setExtra(new byte[]{}); // 设置额外的数据,这里设置为空 entry.setComment("file comment"); // 设置ZipEntry的注释,即文件说明 entry.setCreationTime(FileTime.from(Instant.now())); // 设置文件的创建时间 entry.setLastAccessTime(FileTime.from(Instant.now())); // 设置文件的最后访问时间 entry.setLastModifiedTime(FileTime.from(Instant.now())); // 设置文件的最后修改时间。 // 向ZIP输出流中添加一个ZIP实体,构造方法中的name参数指定文件在ZIP包中的文件名 zos.putNextEntry(entry); // 向ZIP实体中写入内容 byte[] buf = new byte[1024]; int len; while ((len = fis.read(buf)) > 0) { zos.write(buf, 0, len); } // 关闭ZipEntry zos.closeEntry(); } catch (IOException e) { e.printStackTrace(); } } /** * 解压缩ZIP文件 * @param zipFile ZIP文件 * @param destDir 目标路径 */ public static void zipDecompress(File zipFile, File destDir) { byte[] buffer = new byte[1024]; try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile),Charset.forName("GBK"))) { ZipEntry entry = zis.getNextEntry(); if(!destDir.exists()){ destDir.mkdirs(); } while (entry != null) { File file = new File(destDir, entry.getName()); if (entry.isDirectory()) { file.mkdirs(); } else { File parent = file.getParentFile(); if (!parent.exists()) { parent.mkdirs(); } try (FileOutputStream fos = new FileOutputStream(file)) { int len; while ((len = zis.read(buffer)) > 0) { fos.write(buffer, 0, len); } } } entry = zis.getNextEntry(); } } catch (IOException e) { e.printStackTrace(); } } }