- 压缩包内部,若内部节点(文件或目录)名称包含非拉丁文,跨平台传递时,比如压缩方用的utf-8,接收方用的是gbk,Jdk原生解压流解析就会报错,如下:
java.lang.IllegalArgumentException: MALFORMED
at java.util.zip.ZipCoder.toString(ZipCoder.java:58)
at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:300)
at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:122)
- 使用Apach-commons-compress能够获得更好的兼容性,只需引入如下依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.18</version>
</dependency>
- 代码修改:
package com.yang.helper;
import lombok.SneakyThrows;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
/**
* 流zip工具类
*/
public final class StreamZipUtil {
/**
* 解压流
*
* @param inputStream
* @return
*/
@SneakyThrows
public static InputStream unzipStream(InputStream inputStream) {
//Fail-Fast
if (inputStream == null) {
return null;
}
//1.Jdk原生Zip流,会因为文件或文件夹命名所用 字符集编码不匹配,报MALFORMED错(畸形的)
//ZipInputStream zipInputStream = new ZipInputStream(inputStream);
//2.Apach-commons-compress的Zip流,兼容性更好
ZipArchiveInputStream zipInputStream = new ZipArchiveInputStream(inputStream);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while (zipInputStream.getNextEntry() != null) {
int n;
byte[] buff = new byte[1024];
while ((n = zipInputStream.read(buff)) != -1) {
bos.write(buff, 0, n);
}
}
bos.flush();
bos.close();
return new ByteArrayInputStream(bos.toByteArray());
}
/**
* 压缩流
*
* @param txtName
* @param inputStream
* @return
*/
@SneakyThrows
public static ByteArrayOutputStream zipStream(String txtName, ByteArrayInputStream inputStream) {
//Fail-Fast
if (inputStream == null) {
return null;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zipOut = new ZipOutputStream(outputStream);
zipOut.putNextEntry(new ZipEntry(txtName));
int n;
byte[] buffer = new byte[1024];
while ((n = inputStream.read(buffer)) != -1) {
zipOut.write(buffer, 0, n);
}
zipOut.close();
inputStream.close();
outputStream.close();
return outputStream;
}
}