2010-12-23 240 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