1.3.09_C++ Web 編程

什么是 CGI?

公共網關接口(CGI),是一套標準,定義了信息是如何在 Web 服務器和客戶端腳本之間進行交換的。

CGI 規范目前是由 NCSA 維護的,NCSA 定義 CGI 如下:

  • 公共網關接口(CGI),是一種用于外部網關程序與信息服務器(如 HTTP 服務器)對接的接口標準。
  • 目前的版本是 CGI/1.1,CGI/1.2 版本正在推進中。

Web 瀏覽

為了更好地了解 CGI 的概念,讓我們點擊一個超鏈接,瀏覽一個特定的網頁或 URL,看看會發生什么。

您的瀏覽器聯系上 HTTP Web 服務器,并請求 URL,即文件名。

Web 服務器將解析 URL,并查找文件名。如果找到請求的文件,Web 服務器會把文件發送回瀏覽器,否則發送一條錯誤消息,表明您請求了一個錯誤的文件。

Web 瀏覽器從 Web 服務器獲取響應,并根據接收到的響應來顯示文件或錯誤消息。

然而,以這種方式搭建起來的 HTTP 服務器,不管何時請求目錄中的某個文件,HTTP 服務器發送回來的不是該文件,而是以程序形式執行,并把執行產生的輸出發送回瀏覽器顯示出來。

公共網關接口(CGI),是使得應用程序(稱為 CGI 程序或 CGI 腳本)能夠與 Web 服務器以及客戶端進行交互的標準協議。這些 CGI 程序可以用 Python、PERL、Shell、C 或 C++ 等進行編寫。

CGI 架構圖

下圖演示了 CGI 的架構:

CGI 架構

Web 服務器配置

在您進行 CGI 編程之前,請確保您的 Web 服務器支持 CGI,并已配置成可以處理 CGI 程序。所有由 HTTP 服務器執行的 CGI 程序,都必須在預配置的目錄中。該目錄稱為 CGI 目錄,按照慣例命名為 /var/www/cgi-bin。雖然 CGI 文件是 C++ 可執行文件,但是按照慣例它的擴展名是 .cgi。

默認情況下,Apache Web 服務器會配置在 /var/www/cgi-bin 中運行 CGI 程序。如果您想指定其他目錄來運行 CGI 腳本,您可以在 httpd.conf 文件中修改以下部分:

<Directory "/var/www/cgi-bin">
   AllowOverride None
   Options ExecCGI
   Order allow,deny
   Allow from all
</Directory>
 
<Directory "/var/www/cgi-bin">
Options All
</Directory>

在這里,我們假設已經配置好 Web 服務器并能成功運行,你可以運行任意的 CGI 程序,比如 Perl 或 Shell 等。

第一個 CGI 程序

請看下面的 C++ 程序:

#include <iostream>
using namespace std;
 
int main ()
{
    
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>Hello World - 第一個 CGI 程序</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
   cout << "<h2>Hello World! 這是我的第一個 CGI 程序</h2>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

編譯上面的代碼,把可執行文件命名為 cplusplus.cgi,并把這個文件保存在 /var/www/cgi-bin 目錄中。在運行 CGI 程序之前,請使用 chmod 755 cplusplus.cgi UNIX 命令來修改文件模式,確保文件可執行。訪問可執行文件,您會看到下面的輸出:

Hello World! 這是我的第一個 CGI 程序

上面的 C++ 程序是一個簡單的程序,把它的輸出寫在 STDOUT 文件上,即顯示在屏幕上。在這里,值得注意一點,第一行輸出 Content-type:text/html\r\n\r\n。這一行發送回瀏覽器,并指定要顯示在瀏覽器窗口上的內容類型。

您必須理解 CGI 的基本概念,這樣才能進一步使用 Python 編寫更多復雜的 CGI 程序。C++ CGI 程序可以與任何其他外部的系統(如 RDBMS)進行交互。

HTTP 頭信息

行 Content-type:text/html\r\n\r\n 是 HTTP 頭信息的組成部分,它被發送到瀏覽器,以便更好地理解頁面內容。HTTP 頭信息的形式如下:

HTTP 字段名稱: 字段內容
例如

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

還有一些其他的重要的 HTTP 頭信息,這些在您的 CGI 編程中都會經常被用到。

頭信息 | 描述
-- |
Content-type: MIME | 字符串,定義返回的文件格式。例如 Content-type:text/html。
Expires: Date | 信息變成無效的日期。瀏覽器使用它來判斷一個頁面何時需要刷新。一個有效的日期字符串的格式應為 01 Jan 1998 12:00:00 GMT。
Location: URL | 這個 URL 是指應該返回的 URL,而不是請求的 URL。你可以使用它來重定向一個請求到任意的文件。
Last-modified: Date | 資源的最后修改日期。
Content-length: N | 要返回的數據的長度,以字節為單位。瀏覽器使用這個值來表示一個文件的預計下載時間。
Set-Cookie: String | 通過 string 設置 cookie。

CGI 環境變量

所有的 CGI 程序都可以訪問下列的環境變量。這些變量在編寫 CGI 程序時扮演了非常重要的角色。

變量名 | 描述
-- |
CONTENT_TYPE | 內容的數據類型。當客戶端向服務器發送附加內容時使用。例如,文件上傳等功能。
CONTENT_LENGTH | 查詢的信息長度。只對 POST 請求可用。
HTTP_COOKIE | 以鍵 & 值對的形式返回設置的 cookies。
HTTP_USER_AGENT | 用戶代理請求標頭字段,遞交用戶發起請求的有關信息,包含了瀏覽器的名稱、版本和其他平臺性的附加信息。
PATH_INFO | CGI 腳本的路徑。
QUERY_STRING | 通過 GET 方法發送請求時的 URL 編碼信息,包含 URL 中問號后面的參數。
REMOTE_ADDR | 發出請求的遠程主機的 IP 地址。這在日志記錄和認證時是非常有用的。
REMOTE_HOST | 發出請求的主機的完全限定名稱。如果此信息不可用,則可以用 REMOTE_ADDR來獲取 IP 地址。
REQUEST_METHOD | 用于發出請求的方法。最常見的方法是 GET 和 POST。
SCRIPT_FILENAME | CGI 腳本的完整路徑。
SCRIPT_NAME | CGI 腳本的名稱。
SERVER_NAME | 服務器的主機名或 IP 地址。
SERVER_SOFTWARE | 服務器上運行的軟件的名稱和版本。

下面的 CGI 程序列出了所有的 CGI 變量。

#include <iostream>
#include <stdlib.h>
using namespace std;
 
const string ENV[ 24 ] = {                 
        "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",   
        "HTTP_ACCEPT", "HTTP_ACCEPT_ENCODING",             
        "HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION",         
        "HTTP_HOST", "HTTP_USER_AGENT", "PATH",            
        "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT",      
        "REQUEST_METHOD", "REQUEST_URI", "SCRIPT_FILENAME",
        "SCRIPT_NAME", "SERVER_ADDR", "SERVER_ADMIN",      
        "SERVER_NAME","SERVER_PORT","SERVER_PROTOCOL",     
        "SERVER_SIGNATURE","SERVER_SOFTWARE" };   
 
int main ()
{
    
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>CGI 環境變量</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
   cout << "<table border = \"0\" cellspacing = \"2\">";
 
   for ( int i = 0; i < 24; i++ )
   {
       cout << "<tr><td>" << ENV[ i ] << "</td><td>";
       // 嘗試檢索環境變量的值
       char *value = getenv( ENV[ i ].c_str() );  
       if ( value != 0 ){
         cout << value;                                 
       }else{
         cout << "環境變量不存在。";
       }
       cout << "</td></tr>\n";
   }
   cout << "</table><\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

C++ CGI 庫

在真實的實例中,您需要通過 CGI 程序執行許多操作。這里有一個專為 C++ 程序而編寫的 CGI 庫,我們可以從 ftp://ftp.gnu.org/gnu/cgicc/ 上下載這個 CGI 庫,并按照下面的步驟安裝庫:

$tar xzf cgicc-X.X.X.tar.gz 
$cd cgicc-X.X.X/ 
$./configure --prefix=/usr 
$make
$make install

您可以點擊 C++ CGI Lib Documentation,查看相關的庫文檔。

GET 和 POST 方法

您可能有遇到過這樣的情況,當您需要從瀏覽器傳遞一些信息到 Web 服務器,最后再傳到 CGI 程序。通常瀏覽器會使用兩種方法把這個信息傳到 Web 服務器,分別是 GET 和 POST 方法。

使用 GET 方法傳遞信息

GET 方法發送已編碼的用戶信息追加到頁面請求中。頁面和已編碼信息通過 ? 字符分隔開,如下所示:

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

GET 方法是默認的從瀏覽器向 Web 服務器傳信息的方法,它會在瀏覽器的地址欄中生成一串很長的字符串。當您向服務器傳密碼或其他一些敏感信息時,不要使用 GET 方法。GET 方法有大小限制,在一個請求字符串中最多可以傳 1024 個字符。

當使用 GET 方法時,是使用 QUERY_STRING http 頭來傳遞信息,在 CGI 程序中可使用 QUERY_STRING 環境變量來訪問。

您可以通過在 URL 后跟上簡單連接的鍵值對,也可以通過使用 HTML <FORM> 標簽的 GET 方法來傳信息。

簡單的 URL 實例:Get 方法

下面是一個簡單的 URL,使用 GET 方法傳遞兩個值給 hello_get.py 程序。

/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

下面的實例生成 cpp_get.cgi CGI 程序,用于處理 Web 瀏覽器給出的輸入。通過使用 C++ CGI 庫,可以很容易地訪問傳遞的信息:

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 
 
#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h>  
 
using namespace std;
using namespace cgicc;
 
int main ()
{
   Cgicc formData;
   
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>使用 GET 和 POST 方法</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
 
   form_iterator fi = formData.getElement("first_name");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "名:" << **fi << endl;  
   }else{
      cout << "No text entered for first name" << endl;  
   }
   cout << "<br/>\n";
   fi = formData.getElement("last_name");  
   if( !fi->isEmpty() &&fi != (*formData).end()) {  
      cout << "姓:" << **fi << endl;  
   }else{
      cout << "No text entered for last name" << endl;  
   }
   cout << "<br/>\n";
 
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

現在,編譯上面的程序,如下所示:

$g++ -o cpp_get.cgi cpp_get.cpp -lcgicc

生成 cpp_get.cgi,并把它放在 CGI 目錄中,并嘗試使用下面的鏈接進行訪問:

/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

這會產生以下結果:

名:ZARA 
姓:ALI 

簡單的表單實例:GET 方法

下面是一個簡單的實例,使用 HTML 表單和提交按鈕傳遞兩個值。我們將使用相同的 CGI 腳本 cpp_get.cgi 來處理輸入。

<form action="/cgi-bin/cpp_get.cgi" method="get">
名:<input type="text" name="first_name">  <br />
 
姓:<input type="text" name="last_name" />
<input type="submit" value="提交" />
</form>

下面是上述表單的實際輸出,請輸入名和姓,然后點擊提交按鈕查看結果。

使用 POST 方法傳遞信息

一個更可靠的向 CGI 程序傳遞信息的方法是 POST 方法。這種方法打包信息的方式與 GET 方法相同,不同的是,它不是把信息以文本字符串形式放在 URL 中的 ? 之后進行傳遞,而是把它以單獨的消息形式進行傳遞。該消息是以標準輸入的形式傳給 CGI 腳本的。

我們同樣使用 cpp_get.cgi 程序來處理 POST 方法。讓我們以同樣的例子,通過使用 HTML 表單和提交按鈕來傳遞兩個值,只不過這次我們使用的不是 GET 方法,而是 POST 方法,如下所示:

<form action="/cgi-bin/cpp_get.cgi" method="post">
名:<input type="text" name="first_name"><br />
姓:<input type="text" name="last_name" />
 
<input type="submit" value="提交" />
</form>

向 CGI 程序傳遞復選框數據

當需要選擇多個選項時,我們使用復選框。

下面的 HTML 代碼實例是一個帶有兩個復選框的表單:

<form action="/cgi-bin/cpp_checkbox.cgi" 
         method="POST" 
         target="_blank">
<input type="checkbox" name="maths" value="on" /> 數學
<input type="checkbox" name="physics" value="on" /> 物理
<input type="submit" value="選擇學科" />
</form>

下面的 C++ 程序會生成 cpp_checkbox.cgi 腳本,用于處理 Web 瀏覽器通過復選框給出的輸入。

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 
 
#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 
 
using namespace std;
using namespace cgicc;
 
int main ()
{
   Cgicc formData;
   bool maths_flag, physics_flag;
 
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>向 CGI 程序傳遞復選框數據</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
 
   maths_flag = formData.queryCheckbox("maths");
   if( maths_flag ) {  
      cout << "Maths Flag: ON " << endl;  
   }else{
      cout << "Maths Flag: OFF " << endl;  
   }
   cout << "<br/>\n";
 
   physics_flag = formData.queryCheckbox("physics");
   if( physics_flag ) {  
      cout << "Physics Flag: ON " << endl;  
   }else{
      cout << "Physics Flag: OFF " << endl;  
   }
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

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

當只需要選擇一個選項時,我們使用單選按鈕。

下面的 HTML 代碼實例是一個帶有兩個單選按鈕的表單:

<form action="/cgi-bin/cpp_radiobutton.cgi" 
         method="post" 
         target="_blank">
<input type="radio" name="subject" value="maths" 
                                    checked="checked"/> 數學 
<input type="radio" name="subject" value="physics" /> 物理
<input type="submit" value="選擇學科" />
</form>

下面的 C++ 程序會生成 cpp_radiobutton.cgi 腳本,用于處理 Web 瀏覽器通過單選按鈕給出的輸入。

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 
 
#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 
 
using namespace std;
using namespace cgicc;
 
int main ()
{
   Cgicc formData;
  
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>向 CGI 程序傳遞單選按鈕數據</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
 
   form_iterator fi = formData.getElement("subject");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "Radio box selected: " << **fi << endl;  
   }
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

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

當需要向 CGI 程序傳遞多行文本時,我們使用 TEXTAREA 元素。

下面的 HTML 代碼實例是一個帶有 TEXTAREA 框的表單:

<form action="/cgi-bin/cpp_textarea.cgi" 
         method="post" 
         target="_blank">
<textarea name="textcontent" cols="40" rows="4">
請在這里輸入文本...
</textarea>
<input type="submit" value="提交" />
</form>

下面的 C++ 程序會生成 cpp_textarea.cgi 腳本,用于處理 Web 瀏覽器通過文本區域給出的輸入。

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 
 
#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 
 
using namespace std;
using namespace cgicc;
 
int main ()
{
   Cgicc formData;
  
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>向 CGI 程序傳遞文本區域數據</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
 
   form_iterator fi = formData.getElement("textcontent");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "Text Content: " << **fi << endl;  
   }else{
      cout << "No text entered" << endl;  
   }
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

向 CGI 程序傳遞下拉框數據

當有多個選項可用,但只能選擇一個或兩個選項時,我們使用下拉框。

下面的 HTML 代碼實例是一個帶有下拉框的表單:

<form action="/cgi-bin/cpp_dropdown.cgi" 
                       method="post" target="_blank">
<select name="dropdown">
<option value="Maths" selected>數學</option>
<option value="Physics">物理</option>
</select>
<input type="submit" value="提交"/>
</form>

下面的 C++ 程序會生成 cpp_dropdown.cgi 腳本,用于處理 Web 瀏覽器通過下拉框給出的輸入。

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 
 
#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h> 
 
using namespace std;
using namespace cgicc;
 
int main ()
{
   Cgicc formData;
  
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>向 CGI 程序傳遞下拉框數據</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
 
   form_iterator fi = formData.getElement("dropdown");  
   if( !fi->isEmpty() && fi != (*formData).end()) {  
      cout << "Value Selected: " << **fi << endl;  
   }
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

在 CGI 中使用 Cookies

HTTP 協議是一種無狀態的協議。但對于一個商業網站,它需要在不同頁面間保持會話信息。例如,一個用戶在完成多個頁面的步驟之后結束注冊。但是,如何在所有網頁中保持用戶的會話信息。

在許多情況下,使用 cookies 是記憶和跟蹤有關用戶喜好、購買、傭金以及其他為追求更好的游客體驗或網站統計所需信息的最有效的方法。

它是如何工作的

服務器以 cookie 的形式向訪客的瀏覽器發送一些數據。如果瀏覽器接受了 cookie,則 cookie 會以純文本記錄的形式存儲在訪客的硬盤上。現在,當訪客訪問網站上的另一個頁面時,會檢索 cookie。一旦找到 cookie,服務器就知道存儲了什么。

cookie 是一種純文本的數據記錄,帶有 5 個可變長度的字段:

  • Expires : cookie 的過期日期。如果此字段留空,cookie 會在訪客退出瀏覽器時過期。
  • Domain : 網站的域名。
  • Path : 設置 cookie 的目錄或網頁的路徑。如果您想從任意的目錄或網頁檢索 cookie,此字段可以留空。
  • Secure : 如果此字段包含單詞 "secure",那么 cookie 只能通過安全服務器進行檢索。如果此字段留空,則不存在該限制。
  • Name=Value : cookie 以鍵值對的形式被設置和獲取。

設置 Cookies

向瀏覽器發送 cookies 是非常簡單的。這些 cookies 會在 Content-type 字段之前,與 HTTP 頭一起被發送。假設您想設置 UserID 和 Password 為 cookies,設置 cookies 的步驟如下所示:

#include <iostream>
using namespace std;
 
int main ()
{
 
   cout << "Set-Cookie:UserID=XYZ;\r\n";
   cout << "Set-Cookie:Password=XYZ123;\r\n";
   cout << "Set-Cookie:Domain=www.w3cschool.cc;\r\n";
   cout << "Set-Cookie:Path=/perl;\n";
   cout << "Content-type:text/html\r\n\r\n";
 
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>CGI 中的 Cookies</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
 
   cout << "設置 cookies" << endl;  
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

從這個實例中,我們了解了如何設置 cookies。我們使用 Set-Cookie HTTP 頭來設置 cookies。

在這里,有一些設置 cookies 的屬性是可選的,比如 Expires、Domain 和 Path。值得注意的是,cookies 是在發送行 "Content-type:text/html\r\n\r\n 之前被設置的。

編譯上面的程序,生成 setcookies.cgi,并嘗試使用下面的鏈接設置 cookies。它會在您的計算機上設置四個 cookies:

/cgi-bin/setcookies.cgi

獲取 Cookies

檢索所有設置的 cookies 是非常簡單的。cookies 被存儲在 CGI 環境變量 HTTP_COOKIE 中,且它們的形式如下:

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

下面的實例演示了如何獲取 cookies。

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 
 
#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h>
 
using namespace std;
using namespace cgicc;
 
int main ()
{
   Cgicc cgi;
   const_cookie_iterator cci;
 
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>CGI 中的 Cookies</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
   cout << "<table border = \"0\" cellspacing = \"2\">";
   
   // 獲取環境變量
   const CgiEnvironment& env = cgi.getEnvironment();
 
   for( cci = env.getCookieList().begin();
        cci != env.getCookieList().end(); 
        ++cci )
   {
      cout << "<tr><td>" << cci->getName() << "</td><td>";
      cout << cci->getValue();                                 
      cout << "</td></tr>\n";
   }
   cout << "</table><\n";
  
   cout << "<br/>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

現在,編譯上面的程序,生成 getcookies.cgi,并嘗試使用下面的鏈接獲取您的計算機上所有可用的 cookies:

/cgi-bin/getcookies.cgi

這會產生一個列表,顯示了上一節中設置的四個 cookies 以及您的計算機上所有其他的 cookies:

UserID XYZ 
Password XYZ123 
Domain www.w3cschool.cc 
Path /perl 

文件上傳實例

為了上傳一個文件,HTML 表單必須把 enctype 屬性設置為 multipart/form-data。帶有文件類型的 input 標簽會創建一個 "Browse" 按鈕。

<html>
<body>
   <form enctype="multipart/form-data" 
            action="/cgi-bin/cpp_uploadfile.cgi" 
            method="post">
   <p>文件:<input type="file" name="userfile" /></p>
   <p><input type="submit" value="上傳" /></p>
   </form>
</body>
</html>

這段代碼的結果是下面的表單:
文件:選擇文件
上傳

注意:上面的實例已經故意禁用了保存上傳的文件在我們的服務器上。您可以在自己的服務器上嘗試上面的代碼。

下面是用于處理文件上傳的腳本 cpp_uploadfile.cpp:

#include <iostream>
#include <vector>  
#include <string>  
#include <stdio.h>  
#include <stdlib.h> 
 
#include <cgicc/CgiDefs.h> 
#include <cgicc/Cgicc.h> 
#include <cgicc/HTTPHTMLHeader.h> 
#include <cgicc/HTMLClasses.h>
 
using namespace std;
using namespace cgicc;
 
int main ()
{
   Cgicc cgi;
 
   cout << "Content-type:text/html\r\n\r\n";
   cout << "<html>\n";
   cout << "<head>\n";
   cout << "<title>CGI 中的文件上傳</title>\n";
   cout << "</head>\n";
   cout << "<body>\n";
 
   // 獲取要被上傳的文件列表
   const_file_iterator file = cgi.getFile("userfile");
   if(file != cgi.getFiles().end()) {
      // 在 cout 中發送數據類型
      cout << HTTPContentHeader(file->getDataType());
      // 在 cout 中寫入內容
      file->writeToStream(cout);
   }
   cout << "<文件上傳成功>\n";
   cout << "</body>\n";
   cout << "</html>\n";
   
   return 0;
}

上面的實例是在 cout 流中寫入內容,但您可以打開文件流,并把上傳的文件內容保存在目標位置的某個文件中。

代碼鏈接:https://github.com/karst87/cpp/tree/master/learning/com.runoob

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容