2012-07-04 22 views
3

我真的想與表單數據發送簡單的HTML頁面,用戶用GET獲取POST值,然後收到表單變量與POST。 HTML文件看起來像:不能與cgi.FieldStorage

<HTML> 
<title> My Title</title> 
<body> 
<form method="post" action="http.py"> 
<input name="Name" type="text"/> 
<input name="Submit" type="submit" value="Submit" /> 
</form> 
</body> 
</HTML> 

下面是python腳本:

import os 
import cgi 
import sys 
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler 



class customHTTPServer(BaseHTTPRequestHandler): 
     def do_GET(self): 
       self.send_response(200) 
       self.send_header('Content-type', 'text/html') 
       self.end_headers() 
       fh=open('index.html','r') 
       self.wfile.write(fh.read()) 
       return 

     def do_POST(self): 
      form = cgi.FieldStorage() 
      self.send_response(200) 
      self.end_headers() 
      self.wfile.write(form['Name'].value) 


def main(): 
     try: 
      server = HTTPServer(('',9111),customHTTPServer) 
      print 'server started at port 8080' 
      server.serve_forever() 
     except KeyboardInterrupt: 
      server.socket.close() 

if __name__=='__main__': 
     sys.exit(main()) 

但仍的FieldStorage空所有的時間。我已經試圖檢查self.rfile中的內容,並發現如果我嘗試執行self.rfile.readlines(),瀏覽器卡住,看起來像腳本正在等待數據流的結束。從哪裏我應該採取名稱變量,我是提交與POST?

+0

你提交表單前進入你的輸入領域的一些價值?除非您將'keep_blank_values = True'傳遞給其構造函數,否則'cgi.FieldStorage'不會考慮空字段。 –

+0

當然,我做到了。不能老是搞清楚什麼我真的做錯了。還有self.headers都很好,我可以看到內容類型:應用程序/ x-WWW窗體-urlencoded和其他的東西有,但self.rfile是一個問題。 –

+1

它不是一個CGI腳本。看到我的答案。 – jdi

回答

5

我想你可能會在這裏混合了一些概念。你既有服務器的思想也有cgi腳本。無論您的POST操作是什麼(http.py或其他),您的服務器都會接受請求。實際上沒有發生CGI處理。所以,你可以先調整你的HTML模板此爲簡單起見:

<form method="post" action=""> 

然後,你應該參考這個其他問題有關how to read from the request,而不是試圖用CGI的FieldStorage:

import urlparse 

... 

    def do_POST(self): 
     length = int(self.headers.getheader('content-length')) 
     postvars = urlparse.parse_qs(self.rfile.read(length), keep_blank_values=1) 
     self.send_response(200) 
     self.end_headers() 
     self.wfile.write(postvars) 

問題你有,並且因爲這是創建Web服務器應用程序的一種非常低級的方式,如果您無限期地從輸入流中讀取,它將繼續並阻止。您檢查標頭的內容長度並只讀取很多字節。你完全不需要cgi模塊,因爲這不是一個cgi腳本。

CGI腳本的工作原理是在服務器看到的請求是對一個匹配類型和位置的一個文件,並在像一個正常的程序的子過程執行它。它向進程提供參數,然後獲得回覆給客戶端的響應。如果這是一個CGI腳本,服務器將在一個模塊中,永遠運行,並且cgi代碼將會在另一個模塊中用更簡單的代碼來檢查請求。

+0

非常感謝JDI的詳細解釋。我已經通過我自己的測試方法發現了「如何從請求中讀取」主題 - 是的,現在很明顯。事實上,self.rfile層出不窮,這就是爲什麼我無法從它讀取readline(s)。現在我明白了它背後的想法。我真的很需要,可能是「低水平」的事情,因爲我不想讓我的腳本超負荷進口。謝謝。 –

+1

你說「你完全不需要cgi模塊,因爲這不是cgi腳本」,然而你引用的另一個問題(「如何從請求中讀取」)確實使用了cgi模塊(特別是:cgi.parse_header,cgi.parse_multipart和cgi.parse_qs),它也不是CGI腳本。顯然,cgi模塊對於CGI處理不僅僅是有用的。 此外,cgi.parse_multipart的源代碼表明它應該被cgi.FieldStorage包含,所以它看起來像一個涉及cgi.FieldStorage的方法應該是可行的,甚至簡潔。 –

+0

這個回答對於給定的問題是不正確的。 cgi.FieldStorage可以正確處理'application/x-www-form-urlencoded'和'multipart/form-data'(文件上傳)內容類型。給出的示例雖然對於防止對'rfile'文件句柄的阻塞很有用,但不能正確解析'multipart/form-data'。請參閱邁克爾戴克關於這個問題的正確答案的建議。 –

0

這裏是獲取POST變量的方法的URL Here JDI提供了詳細的解釋。

6

在原來的代碼,我只是改了行

form = cgi.FieldStorage() 

form = cgi.FieldStorage(
    fp=self.rfile, 
    headers=self.headers, 
    environ={'REQUEST_METHOD':'POST'}) 

,似乎在按預期工作。

帽尖到http://pymotw.com/2/BaseHTTPServer/爲臨界「ENVIRON」設置。 (默認情況下,cgi.FieldStorage認爲它在處理一個GET請求。)

+0

添加'environ = {'REQUEST_METHOD':'POST'}'爲我做了詭計。 –