2010-12-23 245 views
4

通常,当我想要一个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 

Works为ANSI文件非常精细。但是,比方说,我有一个二进制文件a.exe(该文件位于Web服务器的秘密路径中,用户不能直接访问该目录路径)。我希望使用类似的方法进行传输。我怎么能这样做?

  • 我应该使用什么内容类型?
  • 使用打印似乎已损坏客户端收到的内容。什么是正确的方法?

我使用下面的代码。

#!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

回答

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是不是在文本-mode

1

内容类型的.exe是tipically 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() 
+0

我编辑我的问题,表示有发现“B”标志和内容类型旁边另一个问题。 – 2010-12-23 09:18:59

+0

@Yan看到我的编辑 – systempuntoout 2010-12-23 09:35:01

1

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

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