1

Если на сервер загружен большой zip-файл, и все, что вам нужно, это часть его содержимого, есть ли способ открыть его и выбрать то, что вы хотите загрузить?

3 ответа3

1

Я написал скрипт Python list_remote_zip.py который может перечислять файлы в zip-файле, доступном по HTTP:

import urllib2, struct, sys

def open_remote_zip(url, offset=0):
 return urllib2.urlopen(urllib2.Request(url, headers={'Range': 'bytes={}-'.format(offset)}))

offset = 0
zipfile = open_remote_zip(sys.argv[1])
header = zipfile.read(30)

while header[:4] == 'PK\x03\x04':
 compressed_len, uncompressed_len = struct.unpack('<II', header[18:26])
 filename_len, extra_len = struct.unpack('<HH', header[26:30])
 header_len = 30 + filename_len + extra_len
 total_len = header_len + compressed_len

 print('{}\n offset: {}\n length: {}\n  header: {}\n  payload: {}\n uncompressed length: {}'.format(zipfile.read(filename_len), offset, total_len, header_len, compressed_len, uncompressed_len))
 zipfile.close()

 offset += total_len
 zipfile = open_remote_zip(sys.argv[1], offset)
 header = zipfile.read(30)

zipfile.close()

Он не использует центральный каталог zip-файла, который находится в конце файла. Вместо этого он идет с самого начала и анализирует отдельные локальные заголовки и пропускает полезную нагрузку, надеясь получить другой заголовок. Он отправляет новый запрос каждый раз, когда ему нужно перейти к смещению. Это, конечно, работает только с серверами, которые поддерживают HTTP-заголовок Range .

Нужно только передать URL-адрес zip-файла в качестве аргумента командной строки. Пример использования и вывод должен выглядеть примерно так:

$ python list_remote_zip.py http://dl.xonotic.org/xonotic-0.8.1.zip
Xonotic/Makefile
 offset: 0
 length: 1074
  header: 46
  payload: 1028
 uncompressed length: 5019
Xonotic/source/darkplaces/
 offset: 1074
 length: 56
  header: 56
  payload: 0
 uncompressed length: 0
Xonotic/source/darkplaces/bih.h
 offset: 1130
 length: 1166
  header: 61
  payload: 1105
 uncompressed length: 2508
Xonotic/source/darkplaces/portals.h
 offset: 2296
 length: 334
  header: 65
  payload: 269
 uncompressed length: 648
...

Чтобы скачать один из файлов, я написал еще более унылый скрипт bash get_file_from_remote_zip.sh который использует wget:

info=$(python list_remote_zip.py "$1" | grep -m 1 -A 5 "^$2\$" | tail -n +2)
tmpfile=$(mktemp)

wget --start-pos $(echo "$info" | grep offset | grep -o '[[:digit:]]*') -O - "$1" | head -c $(echo "$info" | grep -m 1 length | grep -o '[[:digit:]]*') >"$tmpfile"

printf '\x1f\x8b' # gzip magic
tail -c +9 <"$tmpfile" | head -c 1 # copy compression method
printf '\0\0\0\0\0\0\x03' # some flags and mtime
tail -c "+$(expr 1 + $(echo "$info" | grep header | grep -o '[[:digit:]]*'))" <"$tmpfile"
tail -c +15 <"$tmpfile" | head -c 4 # The CRCs seem to be compatible.
tail -c +23 <"$tmpfile" | head -c 4

rm "$tmpfile"

Требуется 2 аргумента. Первый - это URL-адрес zip-файла, а второй - извлекаемый файл. Имя файла, подлежащего извлечению, должно быть полным и в точности таким, каким оно отображается в выходных данных предыдущего скрипта Python list_remote_zip.py , который он использует для получения некоторой информации о файле. Затем он использует wget для загрузки с правильным смещением правильной длины. Он сохраняет этот zip-фрагмент во временный файл, который затем используется для вывода файла, отформатированного в gzip , который затем может быть передан в gzip и распакован. Сам по себе "фрагмент" не является допустимым zip-файлом, поскольку в его конце нет центрального каталога. Это можно исправить с помощью опции zip -FF но я решил вместо этого немного изменить заголовки и преобразовать их в файл gzip. Оба (ПК) и почтовый GZIP использовать один и тот же Deflate алгоритм сжатия и даже CRC-32 контрольные суммы , как представляется, совместимы.

Вот пример того, как загрузить случайный файл из архива Xonotic, доступного по адресу http://dl.xonotic.org/xonotic-0.8.1.zip, распаковать его и сохранить в локальном файле:

bash get_file_from_remote_zip.sh http://dl.xonotic.org/xonotic-0.8.1.zip Xonotic/source/darkplaces/mprogdefs.h | gzip -d >mprogdefs.h
0

Если вы обращаетесь к файловому серверу и у вас установлен winrar (и, возможно, другие подобные приложения), вы можете открыть .zip и перетащить нужные файлы.

Если вы говорите о веб-сервере, я не думаю, что вы можете.

0

Предполагая, что сервер поддерживает возобновленную загрузку, теоретически можно написать клиента, который сделал это - захватите достаточно большой блок в конце, чтобы получить каталог, а затем используйте его, чтобы выяснить, что вам нужно захватить, чтобы получить данные. - просто начните загрузку с этой позиции и остановитесь, когда у вас будет достаточно данных. Прошло так много времени с тех пор, как я ковырялся, я не помню, есть ли способ найти начало каталога, кроме грубой силы.

Я никогда не слышал о таком клиенте и не могу себе представить, почему он будет разработан - если это данные, которые разумно будут загружаться по частям, то почему веб-мастер хранит их как один большой zip-файл ???

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .