Есть ли способ загрузить части содержимого zip-файла?

1

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

habibhassani
источник
Так что вопрос действительно общий, но обычно нет. С некоторым сжатым форматом вы можете извлечь часть содержимого из неполного файла rar x --kb myincompletefile.rar. Ибо 7zipувидеть даже этот ответ . Какой тип сервера вы имеете в виду? Вы используете zipпросто сказать сжатый или вы ссылаетесь строго на zipфайлы?
Hastur
я говорю о файле, размещаемом онлайн для загрузки по протоколу http или ftp или даже через торрент, и я имею в виду строго файл .zip.
Хабибхассани
Тогда я боюсь, что ваш ответ будет Нет . :-( Но вы всегда можете начать загрузку, попытаться исправить / извлечь частичную часть и посмотреть, есть ли то, что вам нужно ... Если вы ссылаетесь на распространение программного обеспечения с уникальным zip-файлом под ftp, иногда они имеют «открытая» версия, которую вы можете исследовать как обычный путь ... Я думаю, что-то вроде зеркал CTAN ...
Hastur
Большое спасибо за информацию, я хотел бы сделать ваш комментарий полезным, но я на
первом
Я подозреваю, что это возможно, загрузив заголовок, а затем используя параметры HTTP, связанные с возобновлением частичной загрузки. Если вы программист, вы можете заставить его работать. Однако я не слышал об этом на практике. Получение только части файла - это то, что обычно делается с помощью мультимедиа (аудио / видео) и может использовать потоковую технологию (исторически другие протоколы или надстройки веб-браузера, такие как Flash), на данный момент я не уверен, что HTML5 может сделать подобное). Итак, поскольку я не слышал о том, что это на самом деле делается на практике, я согласен с ответами «нет».
TOOGAM

Ответы:

2

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

Нужно только передать 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
...

Чтобы скачать один из файлов, я написал еще более get_file_from_remote_zip.shунылый скрипт bash, который использует 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-файла, а второй - извлекаемый файл. Имя файла, подлежащего извлечению, должно быть полным и в точности таким, каким оно отображается в выходных данных предыдущего list_remote_zip.pyскрипта Python, которые используются для получения некоторой информации о файле. Затем он использует его wgetдля загрузки с правильным смещением и правильной длиной. Он сохраняет этот zip-фрагмент во временный файл, который затем используется для вывода gzipотформатированного файла, который затем может быть передан по конвейеру и распакован gzip. Сам по себе «фрагмент» не является допустимым zip-файлом, поскольку в его конце нет центрального каталога. Это можно исправить с помощью опции zip's, -FFно я решил вместо этого немного изменить заголовки и преобразовать их в файл gzip. алгоритм сжатия и даже контрольные суммы 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
Карел Влк
источник
Кстати, это помогло.
Карел Влк
я не знаю, как использовать это, но все равно спасибо
habibhassani
Первый блок кода - это скрипт Python (2), который я вызвал list_remote_zip.py. Поэтому, если у вас установлен Python, вы можете запустить его и передать URL-адрес zip-файла в качестве аргумента командной строки следующим образом: python list_remote_zip.py http://dl.xonotic.org/xonotic-0.8.1.zip
Karel Vlk
Второй сценарий - это сценарий оболочки Unix, который должен быть запущен с помощью bash и тому подобного. Я немного расширил ответ, чтобы, надеюсь, сделать его более понятным.
Карел Влк
0

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

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

Джек
источник
0

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

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

Лорен Печтель
источник
Есть случаи, когда вы загружаете большой zip-файл и некоторые его файлы повреждаются, поэтому, если это решение существует, мне будет проще загружать только поврежденные файлы.
Хабибхассани
@habibhassani Другими словами, тот факт, что это zip-файл на самом деле не имеет значения, вы просто хотите восстановить поврежденный фрагмент файла.
Лорен Печтел
точно, этот вопрос основан на моем опыте
habibhassani