使用文件对象时损坏的Zip文件

0 投票
1 回答
21 浏览
提问于 2025-04-14 16:53

我正在尝试用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())

撰写回答