使用文件对象时损坏的Zip文件
我正在尝试用Python创建一个压缩文件,之后会用在HTTP响应中。为此,我使用了一个io.BytesIO()
作为文件对象。
生成的压缩文件似乎有点问题:一些软件像unzip
无法打开它,而其他软件像zcat
却能读取内容。
这里有一个简单的例子,我会把生成的压缩文件保存到文件中,而不是直接在响应中使用。这个错误和我在实际应用中遇到的情况是一样的:
$ cat << EOF > script.py
> import io
import zipfile
with (io.BytesIO() as fo,
zipfile.ZipFile(fo, 'w') as zip,
open('outfile.zip', 'wb') as outfile):
zip.writestr('file.txt', b'Lorem ipsum')
fo.seek(0)
outfile.write(fo.read())
> EOF
$ python3 script.py
$ ll outfile.zip
-rw-rw-r-- 1 neurino neurino 49 mar 11 14:38 outfile.zip
$ unzip outfile.zip
Archive: outfile.zip
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of outfile.zip or
outfile.zip.zip, and cannot find outfile.zip.ZIP, period.
$ zcat outfile.zip
Lorem ipsum
如果用一个实际的文件代替文件对象,生成的压缩文件就能正常工作,而且文件大小也更大。
$ cat << EOF > script2.py
> import io
> import zipfile
> with zipfile.ZipFile('outfile.zip', 'w') as zip:
> zip.writestr('file.txt', b'Lorem ipsum')
$ python3 script2.py
$ ll outfile.zip
-rw-rw-r-- 1 user user 125 mar 11 14:41 outfile.zip
$ unzip outfile.zip
Archive: outfile.zip
extracting: file.txt
1 个回答
1
我自己遇到了这个问题:我在 with zipfile.ZipFile
这个代码块里读取文件对象,但在它的 __exit__
代码块执行之前就开始读取了。
这个脚本按预期工作:
import io
import zipfile
fo = io.BytesIO()
with zipfile.ZipFile(fo, 'w') as zip:
zip.writestr('file.txt', b'Lorem ipsum')
fo.seek(0)
with open('outfile.zip', 'wb') as outfile:
outfile.write(fo.read())