hab*_*ani 2 zip download webserver
如果服务器上上传了一个大的 zip 文件,而您只需要其中的一些内容,是否有办法打开它并选择您要下载的内容?
小智 6
我编写了一个 Python 脚本list_remote_zip.py,可以列出可通过 HTTP 访问的 zip 文件中的文件:
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()
Run Code Online (Sandbox Code Playgroud)
它不使用 zip 文件的中心目录,该目录位于文件末尾附近。相反,它从头开始解析各个本地标头并跳过有效负载,希望到达另一个标头。每次需要跳到某个偏移量时,它都会发送一个新请求。当然,这仅适用于支持RangeHTTP 标头的服务器。
只需要将 zip 文件的 URL 作为命令行参数传递即可。示例用法和输出应如下所示:
$ 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
...
Run Code Online (Sandbox Code Playgroud)
为了下载其中一个文件,我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"
Run Code Online (Sandbox Code Playgroud)
它需要 2 个参数。第一个是 zip 文件的 URL,第二个是要解压的文件。要提取的文件的名称必须完整且与上一个list_remote_zip.pyPython 脚本的输出中显示的名称完全相同,该脚本用于获取有关该文件的一些信息。然后它会wget以正确的偏移量和正确的长度下载它。它将这个 zip“切片”保存到一个临时文件,然后使用该临时文件输出一个gzip格式的文件,然后可以将其通过管道传输到gzip. “切片”本身不是有效的 zip 文件,因为它末尾没有中心目录。zip它可以用的选项修复-FF,但我决定稍微更改标头并将其转换为 gzip 文件。(PK)zip 和 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4659 次 |
| 最近记录: |