Как извлечь один файл из файла удаленного архива? - PullRequest
11 голосов
/ 27 июня 2010

С учетом

  1. URL-адрес архива (например, ZIP-файл)
  2. Полное имя (включая путь) файла внутри этого архива

Я ищу способ (желательно на Java) для создания локальной копии этого файла, без предварительной загрузки всего архива .

Из моего (ограниченного) понимания это возможно, хотя я понятия не имею, как это сделать. Я использовал TrueZip , поскольку он поддерживает большое разнообразие типов архивов, но я сомневаюсь в его способности работать таким образом. У кого-нибудь есть такой опыт?

РЕДАКТИРОВАТЬ: возможность сделать это с tar-архивами и архивами-архивами на молнии также важна для меня.

Ответы [ 4 ]

10 голосов
/ 27 июня 2010

Ну, как минимум, вам нужно загрузить часть архива, включая сжатые данные файла, который вы хотите извлечь. Это предполагает следующее решение: открыть 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);

Это, конечно, не проверено.

5 голосов
/ 28 июня 2010

Вопреки другим ответам здесь, я хотел бы отметить, что записи ZIP сжимаются индивидуально, поэтому (теоретически) вам не нужно загружать ничего, кроме каталога и самой записи.Чтобы это работало, сервер должен поддерживать HTTP-заголовок Range.

Стандартный API Java поддерживает только чтение ZIP-файлов из локальных файлов и входных потоков.Насколько я знаю, нет условий для чтения из удаленных файлов с произвольным доступом.

Поскольку вы используете TrueZip, я рекомендую реализовать de.schlichtherle.io.rof.ReadOnlyFile с использованием Apache HTTP Client и создать de.schlichtherle.util.zip.ZipFile с этим.

Это не даст никаких преимуществ для сжатых архивов TAR, так как весь архив сжимается вместе (кроме простого использования InputStream и его уничтожения, когда у вас есть запись).

3 голосов
/ 28 июля 2011

Начиная с TrueZIP 7.2, в модуле TrueZIP Path появился новый клиентский API. Это реализация NIO.2 FileSystemProvider для JSE 7. Используя этот 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.
    ...
}
0 голосов
/ 28 июня 2010

Я не уверен, есть ли способ извлечь один файл из ZIP без предварительной загрузки всего файла.Но если вы используете ZIP-файл, вы можете создать сервлет Java, который читает 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);
  }
}
...