原文分享:JAVA压缩/解压ZIP/7Z文件(by Apache Commons Compress)
前言
目前手中有个项目,需要做到用户打包图片上传处理的逻辑,这个时候,就需要用到一个JAVA的压缩/解压库Apache Commons Compress
。
- 从压缩文件中逐个读取文件(废话,肯定从里面读啦)。
- 读取文件的文件名进行业务逻辑判断(文件名跟业务编号有关)。
- 上传之后返回一个信息说哪些成功、哪些失败、哪些异常或没有权限。
WHats Apache Commons Compress?
Apache Commons Compress
,Compress是ApacheCommons提供压缩
、解压缩
文件的类库,定义了一个用于处理ar,cpio,Unix dump,tar,zip,gzip,XZ,Pack200,bzip2、7z,arj,lzma,snappy,DEFLATE,lz4,Brotli,Zstandard,DEFLATE64和Z文件的API ,非常强大。
官网 http://commons.apache.org/proper/commons-compress/
POM.xml
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.20</version>
</dependency>
核心代码
假设文件以及成功上传到目标文件夹(本文不涉及上传,只讲解解压)
![c066a030fb0b0a55e37cb49ffa0f0481.png](https://i-blog.csdnimg.cn/blog_migrate/b42b20f14240976af07eb26ebc726ec4.jpeg)
ArchiveInputStream archiveInputStream = factory.createArchiveInputStream(ArchiveStreamFactory.ZIP,inputStream);
代表解压ZIP文件,也支持一下文件:
![8567bb92167253d17e651ad3c36aa2ec.png](https://i-blog.csdnimg.cn/blog_migrate/723982c1fe86518f6318db3abbe8ceb1.jpeg)
业务代码:
public ReturnT importImage(String filename,Integer roleId,Integer userId){
List<String> resultList = new ArrayList<>(24);
File archiveFile = new File(storageService.getPathString()+filename);
File outputDir = new File(storageService.getPathString()+userId);
// 指定文件所用字符集,这里以UTF-8为例
ArchiveStreamFactory factory = new ArchiveStreamFactory("UTF-8");
try {
InputStream inputStream = new FileInputStream(archiveFile);
//暂定解压ZIP文件
ArchiveInputStream archiveInputStream = factory.createArchiveInputStream(ArchiveStreamFactory.ZIP,inputStream);
ArchiveEntry archiveEntry = null;
OutputStream outputStream;
File outputFile;
byte[] buffer = new byte[512];
int bytesRead;
while ((archiveEntry = archiveInputStream.getNextEntry()) != null) {
//获取完整文件名
String filenameInZip =archiveEntry.getName();
//从最后一.开始切割获取证书编号
String certNumber = filenameInZip.substring(0,filenameInZip.lastIndexOf("."));
Cert cert = certMapper.selectOne(new QueryWrapper<Cert>().eq("cert_number",certNumber));
if(cert==null){
log.info("unzip-证书不存在:{} 证书上传者roleId{} userId:{}",certNumber,roleId,userId);
resultList.add(certNumber+":证书不存在");
}else if(roleId==9|| userId.equals(cert.getUserId())){
log.info("unzip-证书上传成功:{} 证书上传者roleId{} userId:{}",certNumber,roleId,userId);
//判断文件对应的certNumber是否拥有权限
outputFile = new File(outputDir, filenameInZip);
if (!outputFile.getParentFile().exists()) {
outputFile.getParentFile().mkdirs();
}
outputStream = new FileOutputStream(outputFile);
// 进行数据拷贝
while ((bytesRead = archiveInputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
cert.setCertImg(userId+"/"+filenameInZip);
cert.setUpdateTime(new Date());
certMapper.updateById(cert);
resultList.add(certNumber+":证书上传成功");
}else{
log.info("unzip-权限错误:{} 证书上传者roleId{} userId:{}",certNumber,roleId,userId);
resultList.add(certNumber+":权限错误");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return ReturnT.SUCCESS(resultList);
}
效果查看
前端可以显示什么上传成功
![64b5a57b7d7a52a075c9446fc15a0c6a.png](https://i-blog.csdnimg.cn/blog_migrate/ef75860dcc0b9bd95fbd1e45a0ed82b8.jpeg)
上传目录可以看到成功的文件已經解压,其它不需要处理的文件已經忽略。
![2b2f4f84b1e16602a41ee53e3da7288e.png](https://i-blog.csdnimg.cn/blog_migrate/1926fcb8081f560580a2f8a274dfb8a4.jpeg)
关于ArchiveStreamFactory
关于ArchiveStreamFactory的信息,可以在一下javadoc中找到,包含解压zip压缩包和压缩成zip安装包。
#ClassInfo
public class ArchiveStreamFactory
extends java.lang.Object
implements ArchiveStreamProvider
#Description:
Factory to create Archive[In|Out]putStreams from names or the first bytes of the InputStream. In order to add other implementations, you should extend ArchiveStreamFactory and override the appropriate methods (and call their implementation from super of course).
### Compressing a ZIP-File:
final OutputStream out = Files.newOutputStream(output.toPath());
ArchiveOutputStream os = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.ZIP, out);
os.putArchiveEntry(new ZipArchiveEntry("testdata/test1.xml"));
IOUtils.copy(Files.newInputStream(file1.toPath()), os);
os.closeArchiveEntry();
os.putArchiveEntry(new ZipArchiveEntry("testdata/test2.xml"));
IOUtils.copy(Files.newInputStream(file2.toPath()), os);
os.closeArchiveEntry();
os.close();
### Decompressing a ZIP-File:
final InputStream is = Files.newInputStream(input.toPath());
ArchiveInputStream in = new ArchiveStreamFactory().createArchiveInputStream(ArchiveStreamFactory.ZIP, is);
ZipArchiveEntry entry = (ZipArchiveEntry)in.getNextEntry();
OutputStream out = Files.newOutputStream(dir.toPath().resolve(entry.getName()));
IOUtils.copy(in, out);
out.close();
in.close();