如何在 Python 中通过 cgi 部署 zip 文件(或其他二进制文件)?

der*_*mai 6 python binary zip cgi python-3.x

我正在使用 Python 和 CGI​​ 编写一个小型网站,用户可以在其中上传 zip 文件和下载其他用户上传的文件。目前,我可以正确上传 zip 文件,但是在将文件正确发送给用户时遇到了一些麻烦。我的第一种方法是:

file = open('../../data/code/' + filename + '.zip','rb')

print("Content-type: application/octet-stream")
print("Content-Disposition: filename=%s.zip" %(filename))
print(file.read())

file.close()
Run Code Online (Sandbox Code Playgroud)

但很快我意识到我必须将文件作为二进制发送,所以我尝试:

print("Content-type: application/octet-stream")
print("Content-Disposition: filename=%s.zip" %(filename))
print('Content-transfer-encoding: base64\r')
print( base64.b64encode(file.read()).decode(encoding='UTF-8') )
Run Code Online (Sandbox Code Playgroud)

以及它的不同变体。它只是行不通;Apache 引发“来自脚本的格式错误的标头”错误,所以我想我应该以其他方式对文件进行编码。

Mar*_*ers 6

您需要在标题后打印一个空行,并且您的 Content-disposition 标题缺少类型 ( attachment):

print("Content-type: application/octet-stream")
print("Content-Disposition: attachment; filename=%s.zip" %(filename))
print()
Run Code Online (Sandbox Code Playgroud)

您可能还想使用一种更有效的方法来上传结果文件;用于shutil.copyfileobj()将数据复制到sys.stdout.buffer

from shutil import copyfileobj
import sys

print("Content-type: application/octet-stream")
print("Content-Disposition: attachment; filename=%s.zip" %(filename))
print()

with open('../../data/code/' + filename + '.zip','rb') as zipfile:
    copyfileobj(zipfile, sys.stdout.buffer)
Run Code Online (Sandbox Code Playgroud)

print()在任何情况下,您都不应该使用二进制数据;你得到的只是b'...'字节文字语法。该sys.stdout.buffer对象是底层的二进制 I/O 缓冲区,将二进制数据直接复制到该缓冲区。


小智 5

标头格式错误,因为出于某种原因,Python 在发送文件后发送它。

您需要做的是在标头之后立即刷新标准输出:

sys.stdout.flush()
Run Code Online (Sandbox Code Playgroud)

然后把文件copy