从Web服务器向客户端提供二进制文件

时间:2010-12-23 08:49:25

标签: python content-type

通常,当我想将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(此文件位于Web服务器的秘密路径中,用户不能直接访问该目录路径)。我希望使用类似的方法来转移。我怎么能这样做?

  • 我应该使用哪种内容类型?
  • 使用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

但是,当我将下载的文件与原始文件进行比较时,似乎每一行后都有一个额外的空格(或更多)。

alt text

4 个答案:

答案 0 :(得分:3)

同意以上关于'rb'和Content-Type标题的海报。

此外:

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

假设这是在CGI环境中的Windows上运行,您将需要使用-u参数启动python进程,这将确保stdout不在文本模式下

答案 1 :(得分: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 :(得分:1)

打开文件时,可以使用open(filename, 'rb') - 'b'标志将其标记为二进制。对于一般处理程序,你可以使用某种形式的mime魔法(我不熟悉从Python中使用它,我几年前才从PHP中使用它)。对于特定情况,.exeapplication/octet-stream

答案 3 :(得分:0)

对于使用Windows Server 2008或2012和Python 3的任何人来说,这里有更新......

经过数小时的实验,我发现以下内容可靠地运作:

import io

with io.open(sys.stdout.fileno(),"wb") as fout:
    with open(filename,"rb") as fin:
        while True:
            data = fin.read(4096)
            fout.write(data)
            if not data:
                break