python cgi 程序demo

http://www.yiibai.com/python/python_cgi_programming.html


什麼是CGI ?

  • 公共網關接口或CGI,Web服務器和一個自定義的腳本之間交換信息是是一組定義的標準..

  • CGI規範在由NCSA和NCSA定義的CGI保持如下:

  • 公共網關接口或CGI,如HTTP服務器信息服務器的標準接口是外部網關方案.

  • 當前版本CGI/1.1和CGI/1.2.

網頁瀏覽

理解CGI的概念,讓我們看看會發生什麼,當我們點擊一個超鏈接到瀏覽特定網頁或URL.

  • 您的瀏覽器觸點的HTTP Web服務器,即需求的URL ie.文件名.

  • Web服務器解析URL,如果發現該文件,然後發送回瀏覽器,否則發送錯誤消息表明您已經請求一個錯誤的文件.

  • Web瀏覽器從Web服務器的響應,並顯示收到的文件或錯誤消息.

但是,它可能設立的HTTP服務器,因此,只要在某個目錄中的文件被請求文件送回,而是作爲一個程序執行,任何方案產出發送您的瀏覽器來顯示。這個函數被調用的通用網關接口或CGI程序稱爲CGI腳本。這些CGI程序可以是一個Python腳本,Perl腳本,shell腳本,C或C+ +程序等.


CGI架構圖

20120717071409_48562.gif

Web服務器的支持與配置

進行CGI編程之前,確保您的Web服務器,支持CGI,它被配置爲CGI程序處理。所有的HTTP服務器執行CGI程序都保存在一個預先配置的目錄。這個目錄被稱爲CGI目錄,並按照慣例,它被命名爲/ var/www/cgi-bin目錄。約定CGI文件.cgi擴展名,但你可以保持你的Python擴展的文件.py.

默認情況下,Linux服務器配置只運行在cgi-bin目錄中的/var/www腳本。如果你想指定的任何其他運行CGI腳本的目錄,內容在httpd.conf文件中的下列行:

AllowOverride None
   Options ExecCGI
   Order allow,deny
   Allow from allOptions All

在這裏,我假設你有Web服務器,併成功運行,你可以運行任何其他CGI程序像Perl或shell等.

第一個CGI 程序

下面是一個簡單的鏈接,鏈接到CGI腳本名爲hello.py。此文件被保存在/var/www/cgi-bin目錄,它有以下內容。運行CGI程序之前,確保你有CHAGE模式使用 UNIX命令chmod命令 755 hello.py,使文件的可執行文件.

#!/usr/bin/python

print "Content-type:text/html\r\n\r\n"
print ''
print ''
print 'Hello Word - First CGI Program'
print ''
print ''
print '

Hello Word! This is my first CGI program

' print '' print ''

如果你點擊hello.py然後,這將產生以下輸出:

Hello Word! This is my first CGI program

這個的hello.py腳本是一個簡單的Python腳本,這是寫在stdout文件,即它的輸出瀏覽器的屏幕。有一個重要的和額外的功能,這是第一行要打印的內容類型:文本/html\R\N\R\N。此行被髮送回瀏覽器,並指定內容類型的瀏覽器屏幕上顯示。現在,你必須理解CGI的基本概念,可以使用Python寫了許多複雜的CGI程序。這個腳本可以與任何其他擴展系統交換,如RDBMS的信息.

HTTP 頭

該行的內容類型:文本/html\R\N\R\n是理解的內容被髮送到瀏覽器的HTTP頭的一部分。所有的HTTP報頭,將在下列表格

HTTP Field Name: Field Content

For Example
Content-type: text/html\r\n\r\n

還有其他一些重要的HTTP頭,你會經常使用的CGI編程.


HeaderDescription
Content-type:A MIME string defining the format of the file being returned. Example is Content-type:text/html
Expires: DateThe date the information becomes invalid. This should be used by the browser to decide when a page needs to be refreshed. A valid date string should be in the format 01 Jan 1998 12:00:00 GMT.
Location: URLThe URL that should be returned instead of the URL requested. You can use this filed to redirect a request to any file.
Last-modified: DateThe date of last modification of the resource.
Content-length: NThe length, in bytes, of the data being returned. The browser uses this value to report the estimated download time for a file.
Set-Cookie: StringSet the cookie passed through the string

CGI環境變量

所有的CGI程序,將有機會獲得以下環境變量。編寫任何CGI程序,這些變量發揮了重要作用.

Variable NameDescription
CONTENT_TYPEThe data type of the content. Used when the client is sending attached content to the server. For example file upload etc.
CONTENT_LENGTHThe length of the query information. It's available only for POST requests
HTTP_COOKIEReturn the set cookies in the form of key & value pair.
HTTP_USER_AGENTThe User-Agent request-header field contains information about the user agent originating the request. Its name of the web browser.
PATH_INFOThe path for the CGI script.
QUERY_STRINGThe URL-encoded information that is sent with GET method request.
REMOTE_ADDRThe IP address of the remote host making the request. This can be useful for logging or for authentication purpose.
REMOTE_HOSTThe fully qualified name of the host making the request. If this information is not available then REMOTE_ADDR can be used to get IR address.
REQUEST_METHODThe method used to make the request. The most common methods are GET and POST.
SCRIPT_FILENAMEThe full path to the CGI script.
SCRIPT_NAMEThe name of the CGI script.
SERVER_NAMEThe server's hostname or IP Address
SERVER_SOFTWAREThe name and version of the software the server is running.

這裏是小的CGI程序列出所有的CGI變量。


#!/usr/bin/python

import os

print "Content-type: text/html\r\n\r\n";
print "Environment<\br>";
for param in os.environ.keys():
  print "%20s: %s<\br>" % (param,os.environ[param])

GET和POST 方法

你所遇到的許多情況下,當您需要從您的瀏覽器,Web服務器,並最終給你的CGI程序傳遞一些信息。最常用的瀏覽器使用兩種方法將此信息傳遞到Web服務器。這些方法是GET方法和POST方法.

使用GET方法傳遞信息:

GET方法發送編碼的用戶信息添加到頁面請求。分隔頁和編碼信息?字符作爲如下:

http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2

GET方法是defualt從瀏覽器向Web服務器的方法來傳遞信息,它會產生一個很長的字符串出現在瀏覽器的位置:框。切勿使用GET方法,如果你有密碼或其他敏感信息傳遞給服務器。 GET方法尺寸limtation:只有1024個字符,可以在請求字符串.

此信息通過使用QUERY_STRING的頭,將通過QUERY_STRING環境變量在你的CGI程序訪問

你可以通過簡單的連接鍵和值對非常久遠的任何URL的信息,或您可以使用HTML標籤來傳遞信息,使用GET方法.

簡單 URL 例子 : Get 方法

這裏是一個簡單的URL使用GET方法,這將通過兩個值hello_get.py方案.

下面是hello_get.py的腳本來處理給定的輸入網頁瀏覽器。我們要使用CGI模塊,這使得它很容易訪問傳遞的信息:

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')

print "Content-type:text/html\r\n\r\n"
print ""
print ""
print "Hello - Second CGI Program"
print ""
print ""
print "

Hello %s %s

" % (first_name, last_name) print "" print ""

This would generate following result:

Hello ZARA ALI

簡單的FORM 例子:GET方法

下面是一個簡單的例子,通過這兩個值,使用HTML表單和提交按鈕。我們將使用相同的CGI腳本hello_get.py的處理此輸入.

First Name:Last Name:

這裏是上述形式的實際輸出,輸入第一個和最後一個名稱,然後點擊提交按鈕來查看結果.


First Name:  
Last Name:  

使用POST方法傳遞信息:

更可靠的信息傳遞給CGI程序的一般方法是POST方法。這包裝完全相同的方式爲GET方法的信息,而是它作爲一個文本字符串發送後?在URL中發送它作爲一個單獨的消息。此消息來自標準輸入的形式到CGI腳本.

下面是同hello_get.py腳本處理的GET以及POST方法.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')

print "Content-type:text/html\r\n\r\n"
print ""
print ""
print "Hello - Second CGI Program"
print ""
print ""
print "

Hello %s %s

" % (first_name, last_name) print "" print ""

讓我們再次看同以上相同的例子,其中通過兩個值,使用HTML表單和提交按鈕。我們將使用相同的CGI腳本hello_get.py的處理此輸入.

First Name:Last Name:

這裏是上述形式的實際輸出,輸入第一個和最後一個名稱,然後點擊提交按鈕來查看結果.


First Name:  
Last Name:  

傳遞複選框(checkbox)數據給CGI程序

複選框用於多個選項被選中時,.

這裏有兩個複選框的形式例如HTML代碼

Maths Physics

這段代碼的結果是下面的形式

Maths  Physics

下面是checkbox.cgi腳本來處理給定的輸入網頁瀏覽器“複選框按鈕.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('maths'):
   math_flag = "ON"
else:
   math_flag = "OFF"

if form.getvalue('physics'):
   physics_flag = "ON"
else:
   physics_flag = "OFF"

print "Content-type:text/html\r\n\r\n"
print ""
print ""
print "Checkbox - Third CGI Program"
print ""
print ""
print "

CheckBox Maths is : %s

" % math_flag print "

CheckBox Physics is : %s

" % physics_flag print "" print ""

單選按鈕數據傳遞給CGI程序

單選按鈕被選中時,只有一個選項是必需的.

這裏是兩個單選按鈕的形式例如HTML代碼:

MathsPhysics

這段代碼的結果是下面的形式

Maths  Physics Physics

下面是radiobutton.py腳本來處理單選按鈕的網頁瀏覽器輸入.

#!/usr/bin/python
# Import modules for CGI handling 
import cgi, cgitb 
# Create instance of FieldStorage 
form = cgi.FieldStorage() 
# Get data from fields
if form.getvalue(" subject'):="" subject="form.getvalue('subject')" else:="" print="" "content-type:text="" html\r\n\r\n"="" ""="" "radio="" -="" fourth="" cgi="" program"="" "Selected Subject is %s" % subject
print ""
print ""

="">

文本區域數據傳遞到CGI程序

TEXTAREA元素時使用多行文字要傳遞給CGI程序.

這裏是一個textarea框的形式例如HTML代碼:

Type your text here...

下面是textarea.cgi的腳本來處理給定的輸入網頁瀏覽器.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('textcontent'):
   text_content = form.getvalue('textcontent')
else:
   text_content = "Not entered"

print "Content-type:text/html\r\n\r\n"
print ""
print "";
print "Text Area - Fifth CGI Program"
print ""
print ""
print "

Entered Text Content is %s

" % text_content print ""

通過下拉框數據到CGI程序

下拉框是用來當我們有很多可供選擇,但只有一個或兩個將被選中.

這裏是一個下拉框的例子表單的HTML代碼

MathsPhysics

這段代碼的結果是下面的形式

20120717140721_42849.jpg

下面是dropdown.py腳本來處理給定的輸入網頁瀏覽器.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('dropdown'):
   subject = form.getvalue('dropdown')
else:
   subject = "Not entered"

print "Content-type:text/html\r\n\r\n"
print ""
print ""
print "Dropdown Box - Sixth CGI Program"
print ""
print ""
print "

Selected Subject is %s

" % subject print "" print ""

使用CGI中的Cookies

HTTP協議是無狀態的協議。但是,對於一個商業網站,它需要保持不同的頁面之間的會話信息。例如,一個用戶註冊完成後,許多網頁結束。但如何保持用戶會話信息的所有網頁.

在許多情況下,使用Cookie的記憶和跟蹤首選項,購買,佣金,其他更好的遊客體驗或網站統計所需的信息是最有效的方法.

它如何工作?

你的服務器發送一些數據到訪問者的瀏覽器Cookie的形式。瀏覽器可以接受的cookie。如果是這樣,它是作爲一個訪問者的硬盤驅動器上的純文本記錄存儲。現在,當遊客到達另一個網站上的網頁,cookie是用於檢索。一旦檢索,您的服務器知道/記得存儲.

Cookie是一個純文本的數據5可變長度字段記錄:

  • Expires : cookie將到期日期。如果是空白,訪問者退出瀏覽器時,cookie將到期.

  • Domain : 您的網站域名.

  • Path : 目錄或網頁設置cookie的路徑。這可能是空白的,如果你想從任何目錄或頁面的cookie檢索.

  • Secure : 目錄或網頁設置cookie的路徑。這可能是空白的,如果你想從任何目錄或頁面的cookie檢索.

  • Name=Value : Cookies是鍵和值對的形式設置和retrviewed.

設置Cookies

這是很容易發送到瀏覽器的cookies。這些cookie將被髮送HTTP頭之前的內容類型提交。假設你要設置用戶名和密碼的cookie。因此Cookie的設置將做如下

#!/usr/bin/python

print "Set-Cookie:UserID=XYZ;\r\n"
print "Set-Cookie:Password=XYZ123;\r\n"
print "Set-Cookie:Expires=Tuesday, 31-Dec-2007 23:12:40 GMT";\r\n"
print "Set-Cookie:Domain=www.yiibai.com;\r\n"
print "Set-Cookie:Path=/perl;\n"
print "Content-type:text/html\r\n\r\n"
...........Rest of the HTML Content....

從這個例子中,你必須瞭解如何設置Cookie。我們使用設置CookieHTTP的頭設置Cookie.

在這裏,它是可選的設置Cookie的屬性,如過期,域和路徑。值得注意的是,Cookie的之前發送行頭 "Content-type:text/html\r\n\r\n.

找回Cookie

這是非常方便地檢索所有的設置Cookie。 Cookie是存儲在CGI環境變量HTTP_COOKIE的,他們將有以下的形式.

key1=value1;key2=value2;key3=value3....

下面是一個如何獲取Cookie的例子.

#!/usr/bin/python

# Import modules for CGI handling 
from os import environ
import cgi, cgitb

if environ.has_key('HTTP_COOKIE'):
   for cookie in map(strip, split(environ['HTTP_COOKIE'], ';')):
      (key, value ) = split(cookie, '=');
      if key == "UserID":
         user_id = value

      if key == "Password":
         password = value

print "User ID  = %s" % user_id
print "Password = %s" % password

這將產生以下結果由上面的腳本設置的cookie:

User ID = XYZ
Password = XYZ123

文件上傳的例子:

上傳文件的HTML表單必須有enctype屬性設置了multipart / form-數據。與該文件類型的輸入標記將創建一個“瀏覽”按鈕.

File:

這段代碼的結果是下面的形式:

20120717142255_98868.jpg

注: 上面的例子已被禁用,故意人上傳的文件保存在我們的服務器上。但你可以嘗試上面的代碼與您的服務器.

這裏是處理文件上傳的的腳本save_file.py:

#!/usr/bin/python

import cgi, os
import cgitb; cgitb.enable()

form = cgi.FieldStorage()

# Get filename here.
fileitem = form['filename']

# Test if the file was uploaded
if fileitem.filename:
   # strip leading path from file name to avoid 
   # directory traversal attacks
   fn = os.path.basename(fileitem.filename)
   open('/tmp/' + fn, 'wb').write(fileitem.file.read())

   message = 'The file "' + fn + '" was uploaded successfully'
   
else:
   message = 'No file was uploaded'
   
print """\
Content-Type: text/html\n

%s

""" % (message,)

Note:如果你是以上腳本運行在Unix / Linux,那麼你會採取如下替換文件分隔,否則您的Windows上述open()語句應該正常工作.

fn = os.path.basename(fileitem.filename.replace("\\", "/" ))

如何提高“文件下載”對話框 ?

有時你想給其中一個用戶點擊一個鏈接,它會彈出“文件下載”對話框的用戶,而不是顯示實際內容的選項。這是很容易的,將通過HTTP頭achived。
這個HTTP頭會從上一節中提到的頭是不同的.

例如,如果你想從一個給定的鏈接文件名文件下載,那麼它的語法如下.

#!/usr/bin/python

# HTTP Header
print "Content-Type:application/octet-stream; name=\"FileName\"\r\n";
print "Content-Disposition: attachment; filename=\"FileName\"\r\n\n";

# Actual File Content will go hear.
fo = open("foo.txt", "rb")

str = fo.read();
print str

# Close opend file
fo.close()


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章