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


1

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


Так что вопрос действительно общий, но обычно нет. С некоторым сжатым форматом вы можете извлечь часть содержимого из неполного файла 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.