【问题标题】:How to extract a single file from a remote archive file?如何从远程存档文件中提取单个文件?
【发布时间】:2011-03-08 17:43:17
【问题描述】:

给定

  1. 存档的 URL(例如 zip 文件)
  2. 该存档中文件的全名(包括路径)

我正在寻找一种方法(最好使用 Java)来创建该文件的本地副本,无需先下载整个存档

根据我的(有限的)理解,这应该是可能的,尽管我不知道该怎么做。我一直在使用TrueZip,因为它似乎支持多种归档类型,但我怀疑它以这种方式工作的能力。有没有人有这方面的经验?

编辑: 能够使用 tarball 和 zipped tarball 也能做到这一点对我来说也很重要。

【问题讨论】:

    标签: java download extract tar archive


    【解决方案1】:

    嗯,至少,您必须下载存档的一部分,包括您要提取的文件的压缩数据。这建议了以下解决方案:打开一个URLConnection 到存档,获取它的输入流,将它包装在一个ZipInputStream 中,并重复调用getNextEntry()closeEntry() 来遍历文件中的所有条目,直到你到达你想要的那个。然后你可以使用ZipInputStream.read(...)读取它的数据。

    Java 代码如下所示:

    URL url = new URL("http://example.com/path/to/archive");
    ZipInputStream zin = new ZipInputStream(url.getInputStream());
    ZipEntry ze = zin.getNextEntry();
    while (!ze.getName().equals(pathToFile)) {
        zin.closeEntry(); // not sure whether this is necessary
        ze = zin.getNextEntry();
    }
    byte[] bytes = new byte[ze.getSize()];
    zin.read(bytes);
    

    当然,这是未经测试的。

    【讨论】:

    • 谢谢;这似乎运作良好(除了小错误),但不幸的是,这只能处理 zip 档案。
    • 好吧,你为什么认为它叫ZipInputStream? ;-) 如果您浏览互联网,您可能会找到一个TarInputStream,您可以使用大致相同的方式 - 如果没有,您可以自己编写。这很容易,因为 tar 文件没有被压缩,它基本上只是每个文件的标题,后跟文件数据。 (维基百科对格式有描述)对于 gzip 压缩的 tar 档案,Java 的标准库有一个 GZIPInputStream 可以与 tar 流一起使用。
    • 确实,Apache 有一个TarInputStream 类:)
    • 很好的解决方案,只是一个小的调整欢呼! ZipInputStream zin = new ZipInputStream(url.openStream());
    【解决方案2】:

    与此处的其他答案相反,我想指出 ZIP 条目是单独压缩的,因此(理论上)您不需要下载目录和条目本身以外的任何内容。服务器需要支持Range HTTP 标头才能正常工作。

    标准 Java API 仅支持从本地文件和输入流中读取 ZIP 文件。据我所知,没有从随机访问远程文件中读取的规定。

    由于您使用的是 TrueZip,我建议使用 Apache HTTP 客户端实现 de.schlichtherle.io.rof.ReadOnlyFile 并使用它创建一个 de.schlichtherle.util.zip.ZipFile

    这不会为压缩的 TAR 存档提供任何优势,因为整个存档是一起压缩的(不仅仅是使用 InputStream 并在输入时将其终止)。

    【讨论】:

      【解决方案3】:

      从 TrueZIP 7.2 开始,模块 TrueZIP 路径中有一个新的客户端 API。这是 JSE 7 的 NIO.2 FileSystemProvider 的实现。使用此 API,您可以访问 HTTP URI,如下所示:

      Path path = new TPath(new URI("http://acme.com/download/everything.tar.gz/README.TXT"));
      try (InputStream in = Files.newInputStream(path)) {
          // Read archive entry contents here.
          ...
      }
      

      【讨论】:

        【解决方案4】:

        我不确定是否有办法从 ZIP 中提取单个文件而无需先下载整个文件。但是,如果您是托管 ZIP 文件的人,您可以创建一个 Java servlet,它读取 ZIP 文件并在响应中返回请求的文件:

        public class GetFileFromZIPServlet extends HttpServlet{
          @Override
          public void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException{
            String pathToFile = request.getParameter("pathToFile");
        
            byte fileBytes[];
            //get the bytes of the file from the ZIP
        
            //set the appropriate content type, maybe based on the file extension
            response.setContentType("...");
        
            //write file to the response
            response.getOutputStream().write(fileBytes);
          }
        }
        

        【讨论】:

        • 不幸的是,我不是托管文件的人......但这是一个好点。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-15
        • 1970-01-01
        • 1970-01-01
        • 2015-12-13
        • 2013-11-27
        • 1970-01-01
        相关资源
        最近更新 更多