【问题标题】:Java utility library for Nested ZIP file handling用于嵌套 ZIP 文件处理的 Java 实用程序库
【发布时间】:2016-05-22 02:00:45
【问题描述】:

我知道 Oracle 注意到 ZIP/GZIP 文件压缩器/解压缩器方法 on their website。但是我有一个场景,我需要扫描并找出是否涉及任何嵌套的 ZIP/RAR。比如下面这种情况:

-MyFiles.zip
   -MyNestedFiles.zip
        -MyMoreNestedFiles.zip
           -MoreProbably.zip
        -Other_non_zips
   -Other_non_zips
-Other_non_zips

我知道 apache commons compress 包和 java.util.zip 是广泛使用的包,commons compress 实际上满足了 java.util.zip 中缺少的功能,例如进行压缩时的一些字符设置。但是我不确定的是用于通过嵌套 zip 文件递归的实用程序,并且 SO 上提供的答案并不是这样做的很好的例子。我尝试了以下代码(我从 Oracle 博客获得),但正如我所怀疑的,嵌套目录递归失败,因为它根本找不到文件:

public static void processZipFiles(String pathName) throws Exception{
        ZipInputStream zis  = null;
        InputStream  is = null;
        try {
          ZipFile zipFile = new ZipFile(new File(pathName));
          String nestPathPrefix = zipFile.getName().substring(0, zipFile.getName().length() -4);
          for(Enumeration e = zipFile.entries(); e.hasMoreElements();){
           ZipEntry ze = (ZipEntry)e.nextElement();
            if(ze.getName().contains(".zip")){
              is = zipFile.getInputStream(ze);
              zis = new ZipInputStream(is);
              ZipEntry zentry = zis.getNextEntry();

              while (zentry!=null){
                  System.out.println(zentry.getName());
                  zentry = zis.getNextEntry();
                  ZipFile nestFile = new ZipFile(nestPathPrefix+"\\"+zentry.getName());
                  if (zentry.getName().contains(".zip")) {
                      processZipFiles(nestPathPrefix+"\\"+zentry.getName());
                  }
              }
              is.close();
            }
          }
        } catch (FileNotFoundException e) {
          e.printStackTrace();
        } catch (IOException e) {
          e.printStackTrace();
        } finally{
            if(is != null)
                is.close();
            if(zis!=null)
                zis.close();
        }
    }  

可能是我做错了什么——或者使用了错误的工具。我的目标是确定是否有任何文件或嵌套的 zip 文件具有我不允许的文件扩展名。这是为了确保我可以阻止我的用户上传被禁止的文件,即使他们正在压缩文件。我还可以选择使用可以进行递归解析的 Tika(使用 Zukka Zitting 的解决方案),但我不确定是否可以使用元数据来按照我的意愿进行检测。

感谢任何帮助/建议。

【问题讨论】:

  • 您不应该从外部 zip 条目的输入流中打开嵌套 Zip,而不是按文件名(因为文件在 zip 中而不是文件系统上,所以这不起作用)?

标签: java recursion zip apache-tika apache-commons-compress


【解决方案1】:

使用 Commons Compress 会更容易,尤其是因为它在各种解压缩器之间具有合理的共享接口,这让生活更轻松 + 允许同时处理其他压缩格式(例如 Tar)

如果你只想使用内置的 Zip 支持,我建议你这样做:

File file = new File("outermost.zip");
FileInputStream input = new FileInputStream(file);
check(input, file.toString());

public static void check(InputStream compressedInput, String name) {
   ZipInputStream input = new ZipInputStream(compressedInput);
   ZipEntry entry = null;
   while ( (entry = input.getNextEntry()) != null ) {
      System.out.println("Found " + entry.getName() + " in " + name);
      if (entry.getName().endsWith(".zip")) { // TODO Better checking
         check(input, name + "/" + entry.getName());
      }
   }
}

当您尝试将outer.zip 中的inner.zip 作为本地文件读取时,您的代码将失败,但它不作为独立文件存在。上面的代码会将以.zip结尾的东西作为另一个zip文件处理,并且会递归

您可能希望使用 commons compress,因此您可以使用备用文件名、其他压缩格式等处理事情

【讨论】:

  • 这是一个简单的解决方案,但不会通过 .RAR 递归。我尝试使用 Tika,但解析元数据需要很长时间(可能是因为它正在解析整个内容)。
  • 我可以看到我可以将 ZipInputStream 替换为 ZipArchiveInputStream 但我将哪个流用于 RAR/TAR。我应该一直保持ArchiveInputStream 和ArchiveEntry 吗?
  • 如果您想使用 Commons Compress 处理所有格式,请使用通用存档类。有关这样做的一个很好的例子,请参阅Apache Tika packages parser source code
  • "@Gagravarr" 我认为问题在于 .RAR 具有 JDK 在内置 API 中没有的特定许可问题(就此而言,commons 也没有压缩),但 Tika似乎以某种方式通过其他方式拥有它。最好知道它用于 RAR 的库以及这是否是 apache 基金会的一部分。
  • @ha9u63ar 您可以在 Apache Tika Parsers pom 文件中找到详细信息 - 它是 com.github.junrar / junrar
猜你喜欢
  • 1970-01-01
  • 2011-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 2021-09-14
  • 2012-09-16
  • 1970-01-01
相关资源
最近更新 更多