Existe uma maneira de baixar partes do conteúdo de um arquivo zip?

1

Se houver um grande arquivo zip carregado em um servidor, e tudo que você precisa é de algum conteúdo, existe uma maneira de abri-lo e escolher o que você deseja fazer o download?

    
por habibhassani 02.10.2015 / 17:18

3 respostas

1

Eu escrevi um script Python list_remote_zip.py que pode listar arquivos em um arquivo zip acessível por 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()

Ele não usa o diretório central do arquivo zip, que está perto do final do arquivo. Em vez disso, ele vai desde o início e analisa cabeçalhos locais individuais e pula a carga útil, esperando pousar em outro cabeçalho. Ele envia uma nova solicitação toda vez que precisa pular para um deslocamento. Obviamente, isso só funciona com servidores que suportam o cabeçalho Range HTTP.

Só precisa ser passado o URL para o arquivo zip como um argumento de linha de comando. Exemplo de uso e saída deve ser algo como isto:

$ 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
...

Para baixar um dos arquivos, eu escrevi um script get_file_from_remote_zip.sh bash ainda mais feio ao redor dele que usa 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 '
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
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()
$ 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
...
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 '
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
%pre%%pre%%pre%%pre%%pre%\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"
%pre%%pre%\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"

São necessários dois argumentos. A primeira é a URL do arquivo zip e a segunda o arquivo a ser extraído. O nome do arquivo a ser extraído deve ser completo e exatamente como aparece na saída do script list_remote_zip.py Python anterior, que ele usa para obter algumas informações sobre o arquivo. Em seguida, ele usa wget para fazer o download no deslocamento correto com o comprimento correto. Ele salva o zip "slice" em um arquivo temporário, que é usado para gerar um arquivo gzip -formatted, que pode ser canalizado e descompactado com gzip . O "slice" em si não é um arquivo zip válido porque não possui um diretório central no final. Pode ser corrigido com a opção zip -FF , mas eu decidi mudar um pouco os cabeçalhos e convertê-los em um arquivo gzip. Ambos (PK) zip e gzip usam o mesmo algoritmo de compressão deflacionar e até mesmo as sondas de verificação CRC-32 parecem compatíveis. / p>

Aqui está um exemplo de como baixar um arquivo aleatório do arquivo do Xonotic disponível no link , descomprimir e salve-o em um arquivo local:

%pre%     
por 14.10.2015 / 16:10
0

Se você estiver acessando um servidor de arquivos e tiver o winrar (e provavelmente outros aplicativos similares) instalado, você poderá abrir o arquivo .zip e arrastar os arquivos desejados.

Se você está falando de um servidor web, não acho que você possa.

    
por 02.10.2015 / 17:24
0

Supondo que o servidor suporta downloads reiniciados, seria possível, em teoria, escrever um cliente que fez isso - pegar um bloco grande o suficiente perto do final para obter o diretório, então usar isso para descobrir o que você precisa pegar para realmente obter os dados - basta iniciar o download nessa posição e parar quando houver dados suficientes. Faz tanto tempo desde que eu estava bisbilhotando que não lembro se há um meio de encontrar o início do diretório que não seja a força bruta.

Eu nunca ouvi falar desse cliente e não posso imaginar por que um seria desenvolvido - se os dados que razoavelmente seriam baixados em pedaços, então por que o webmaster é armazenado como um grande arquivo zip? / p>     

por 03.10.2015 / 06:45