鉴于
我正在寻找一种方法(最好是用Java)来创建该文件的本地副本,而不先下载整个存档。
从我(有限的)理解应该是可能的,虽然我不知道该怎么做。我一直在使用TrueZip,因为它似乎支持各种各样的存档类型,但我对它以这种方式工作的能力存有疑虑。有没有人有这方面的经验?
编辑:能够用tarball和压缩的tarball做到这一点对我来说也很重要。
答案 0 :(得分:9)
嗯,至少,你必须下载档案的一部分,包括你想要提取的文件的压缩数据。这表明以下解决方案:打开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);
当然,这是未经测试的。
答案 1 :(得分:5)
与此处的其他答案相反,我想指出ZIP条目是单独压缩的,因此(理论上)您不需要下载除目录和条目本身之外的任何内容。服务器需要支持Range
HTTP标头才能生效。
标准Java API仅支持从本地文件和输入流中读取ZIP文件。据我所知,没有从随机访问远程文件中读取的规定。
由于您使用的是TrueZip,我建议您使用Apache HTTP Client实现de.schlichtherle.io.rof.ReadOnlyFile
并使用它创建de.schlichtherle.util.zip.ZipFile
。
这不会为压缩的TAR压缩文件提供任何优势,因为整个存档被压缩在一起(除了使用InputStream并在您输入时将其终止)。
答案 2 :(得分:2)
自TrueZIP 7.2以来,模块TrueZIP Path中有一个新的客户端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.
...
}
答案 3 :(得分:0)
我不确定是否有办法从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);
}
}