从web服务器向客户端传递二进制文件
通常,当我想把一个网页服务器上的文本文件传给客户端时,我会这样做:
import cgi
print "Content-Type: text/plain"
print "Content-Disposition: attachment; filename=TEST.txt"
print
filename = "C:\\TEST.TXT"
f = open(filename, 'r')
for line in f:
print line
这样做对于ANSI格式的文件效果很好。但是,假设我有一个二进制文件 a.exe
(这个文件在网页服务器的一个秘密路径下,用户不能直接访问那个目录)。我想用类似的方法来传输这个文件。我该怎么做呢?
- 我应该使用什么样的内容类型?
- 使用打印(print)似乎会导致客户端收到的内容出现损坏。正确的方法是什么?
我使用了以下代码:
#!c:/Python27/python.exe -u
import cgi
print "Content-Type: application/octet-stream"
print "Content-Disposition: attachment; filename=jstock.exe"
print
filename = "C:\\jstock.exe"
f = open(filename, 'rb')
for line in f:
print line
但是,当我把下载的文件和原始文件进行比较时,发现每一行后面似乎多了一个空格(或者更多)。
4 个回答
1
.exe
文件的内容类型通常是application/octet-stream
,这表示它是一个二进制文件。
你可以用open(filename, 'rb')
来打开这个文件,其中的b
表示以二进制模式读取。
为了避免空格问题,你可以试试下面的方法:
sys.stdout.write(open(filename,"rb").read())
sys.stdout.flush()
或者更好的方法是,根据你的文件大小,使用Knio的方法:
fo = open(filename, "rb")
while True:
buffer = fo.read(4096)
if buffer:
sys.stdout.write(buffer)
else:
break
fo.close()
2
在打开一个文件的时候,你可以用 open(filename, 'rb')
这个方式,其中的 'b' 表示你要以二进制的方式打开文件。对于一般的文件处理,你可以使用一些类似于“mime magic”的东西(我对在Python中怎么用不太了解,几年前我只在PHP中用过)。具体来说,.exe
文件的类型是 application/octet-stream
。
3
我同意上面提到的关于'rb'和内容类型头的看法。
另外:
for line in f:
print line
在处理二进制文件时,如果遇到 \n
或 \r\n
这些字节,可能会出现问题。这样做可能会更好:
import sys
while True:
data = f.read(4096)
sys.stdout.write(data)
if not data:
break
假设你是在Windows的CGI环境下运行这个程序,你需要用 -u
参数来启动Python进程,这样可以确保标准输出不是以文本模式运行。