【已解决】Java zip解压时候 malformed input off : 4, length : 1
2023-12-17 10:45:12
需求:通过页面上传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();
}
}
分析原因:
然后查询后得到:
如果在Java中解压文件时报错 “malformed”,通常表示压缩文件的格式不正确或损坏。下面是一些可能导致此错误的常见原因和解决方法:
我试了集中方法都不行,最后看有人说是编码问题,加上GBK编码格式后解析成功
File file = new File(filePath);
? ? ? ? ? ? InputStream inputStream = new FileInputStream(file,Charset.forName("GBK"));
解决方案:
所以修改代码,在生产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();
}
}
}
文章来源:https://blog.csdn.net/kaizi_1992/article/details/135041475
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!