1. 程式人生 > >http post傳送檔案詳解

http post傳送檔案詳解

  首先客戶端連結 192.168.24.56 後, 應該傳送如下http 請求:

  Accept: text/plain, */* 
  Accept-Language: zh-cn 
  Host: 192.168.24.56
  Content-Type:multipart/form-data;boundary=-----------------------------7db372eb000e2
  User-Agent: WinHttpClient 
  Content-Length: 3693
  Connection: Keep-Alive

  -------------------------------7db372eb000e2

Content-Disposition: form-data; name="file"; filename="kn.jpg"

  Content-Type: image/jpeg

  (此處省略jpeg檔案二進位制資料...)

-------------------------------7db372eb000e2--

此內容必須一字不差,包括最後的回車,紅色字型部分就是協議的頭。給伺服器上傳資料時,並非協議頭每個欄位都得說明,其中,content-type是必須的,它包括一個類似標誌性質的名為boundary的標誌,它可以是隨便輸入的字串。對後面的具體內容也是必須的。它用來分辨一段內容的開始。

Content-Length: 3693 ,這裡的3693是要上傳檔案的總長度。綠色字型部分就是需要上傳的資料,可以是文字,也可以是圖片等。資料內容前面需要有Content-Disposition, Content-Type以及Content-Transfer-Encoding等說明欄位。最後的紫色部分就是協議的結尾了。

注意這一行:

  Content-Type: multipart/form-data; boundary=---------------------------7db372eb000e2

  根據 rfc1867, multipart/form-data是必須的. 
  ---------------------------

7db372eb000e2 是分隔符,分隔多個檔案、表單項。其中b372eb000e2 是即時生成的一個數字,用以確保整個分隔符不會在檔案或表單項的內容中出現。Form每個部分用分隔符分割,分隔符之前必須加上"--"著兩個字元(即--{boundary})才能被http協議認為是Form的分隔符,表示結束的話用在正確的分隔符後面新增"--"表示結束。

  前面的 ---------------------------7d 是 IE 特有的標誌,Mozila 為---------------------------71.  

  例如Contect-Type:image/jpeg 表示下面的資料是jpeg檔案資料

*******************************************************************************************************************************

HTTP響應  
  在接收和解釋請求訊息後,伺服器會返回一個HTTP響應訊息。  

   
  與HTTP請求類似,HTTP響應也是三個部分組成,分別是:  
  狀態行、訊息報頭、響應正文。  
   
  狀態行:  
  狀態行由協議版本、數字形式的狀態程式碼、及相應的狀態描述,各元素之間以空格分隔。  
   
  格式:       HTTP-Version   Status-Code   Reason-Phrase   CRLF  
   
  例如:       HTTP/1.1   200   OK   \r\n  
   
  狀態程式碼:  
  狀態程式碼由3位數字組成,表示請求是否被理解或被滿足。  
   
  狀態描述:  
  狀態描述給出了關於狀態程式碼的簡短的文字描述。  
   
  狀態程式碼的第一個數字定義了響應的類別,後面兩位沒有具體的分類。  
  第一個數字有五種可能的取值:  
  -   1xx:     指示資訊—表示請求已接收,繼續處理。  
  -   2xx:     成功—表示請求已經被成功接收、理解、接受。  
  -   3xx:     重定向—要完成請求必須進行更進一步的操作。  
  -   4xx:     客戶端錯誤—請求有語法錯誤或請求無法實現。  
  -   5xx: 伺服器端錯誤—伺服器未能實現合法的請求。    
   
  狀態程式碼 狀態描述 說明  
      200       OK 客戶端請求成功  
      400               Bad   Request 由於客戶端請求有語法錯誤,不能被伺服器所理解。  
      401               Unauthonzed 請求未經授權。這個狀態程式碼必須和WWW-Authenticate報頭域一起使用  
      403 Forbidden 伺服器收到請求,但是拒絕提供服務。伺服器通常會在響應正文中給出不提供服務的原因  
      404 Not   Found 請求的資源不存在,例如,輸入了錯誤的URL。  
      500       Internal   Server   Error 伺服器發生不可預期的錯誤,導致無法完成客戶端的請求。  
      503         Service   Unavailable 伺服器當前不能夠處理客戶端的請求,在一段時間之後,伺服器可能會恢復正常。
HTTP訊息  
  HTTP訊息由客戶端到伺服器的請求和伺服器到客戶端的響應組成。請求訊息和響應訊息都是由開始行,訊息報頭(可選的),空行(只有CTLF的行),訊息正文(可選的)組成。  
  對於請求訊息,開始行就是請求行。  
  對於響應訊息,開始行就是狀態行。     
   
  訊息報頭  
  HTTP訊息報頭包括普通報頭、請求報頭、響應報頭、實體報頭。  
  每一個報頭域都是由(名字+":"+空格+值)組成,訊息報頭域的名字是大小寫無關的。 
   
  普通報頭:  
  在普通報頭中,有少數報頭域應用於所有的請求和響應訊息,但並不用於被傳輸的實體,這些報頭域只用於傳輸的訊息。  
  常用的普通報頭域:Cache-Control,Date,Connection,Pragma.  
   
  請求報頭:  
  請求報頭允許客戶端向伺服器端傳遞該請求的附加資訊以及客戶端自身的資訊。  
  常用的請求報頭域:  
  Accept  
        Accept請求報頭域用語指定客戶端接受哪些型別的資訊。例如:Accept:   image/gif,表明客戶端希望接受GIF圖象格式的資源;Accept:   text/html,表明客戶端希望接受html文字。  
  Accept-Charset  
        Accept-Charset請求報頭域用於指定客戶端接受的字符集。例如:Accept-Charset:   ios-8859-1,gb2312。如果在請求訊息中沒有設定這個域,預設是任何字符集都可以接受。  
  Accept-Encoding  
        Accept-Encoding請求報頭域類似Accept,但是它是用於指定可接受的內容編碼。例如:Accept-Encoding:   gzip,deflate。如果請求訊息中沒有設定這個域,伺服器假定客戶端對各種內容編碼都可接受。  
  Accept-Language  
        Accept-Language請求報頭域類似於Accept,但是它是用於指定一種自然語言。例如:Accept-Language:   zh-cn。如果請求訊息中沒有設定這個域,伺服器假定客戶端對各種語言都可接受。  
  Authorization  
        Authorization請求報頭域主要用於證明客戶端有權檢視某個資源。當瀏覽器訪問一個頁面時,如果收到伺服器的響應程式碼為401(未授權),可以傳送一個包含Authorization請求報頭域的請求,要伺服器對其進行驗證。  
  Host  
        Host請求報頭域主要用於指定被請求資源的Internet主機和埠號,它通常是從HTTP   URL中提取出來的。  
  例如:http://www.sunxin.org/index.html。瀏覽器傳送的請求訊息中,就會包含Host請求報頭域,如下:Host:   www.sunxin.org  
  後面沒有跟埠號,表明使用的是預設埠號80,如果埠號不是80,那麼就要在主機名後面加上一個冒號(":"),然後接上埠號,例如:  
  Host:   www.sunxin.org:8080。     要注意的是,在傳送HTTP請求的時候,這個報頭域是必須的。  
  User-Agent  
        User-Agent允許客戶端將它的作業系統瀏覽器和其他屬性告訴伺服器。我們上網登陸論壇的時候,往往看到些歡迎資訊,其中列出了你的作業系統的名稱和版本等等資訊。原因是:伺服器從User-Agent請求報頭域中獲取的這些資訊,自己編寫瀏覽器可以不用這個請求報頭域。伺服器就無法得知了。
   
  --------------------------------------------------  
  響應報頭  
  響應報頭允許伺服器傳遞不能放在狀態行中的附加響應資訊,以及關於伺服器的資訊和對Request-URI所標識的資源進行下一步訪問的資訊。  
  常用的響應報頭域:  
  Location  
        Location響應報頭域用於重定向接受者到一個新的位置。例如:客戶端所請求的頁面已不存在原先的位置,為了讓客戶端重定向到這個頁面新的位置,伺服器端可以發回Location響應報頭後使用重定向語句,讓客戶端去訪問新的域名所對應的伺服器上的資源。當我們在JSP中使用重定向語句的時候,伺服器端向客戶端發回的響應報頭中,就會有Location響應報頭域。下面是Location響應報頭域的一個例子:Location:   http://www.sunxin.org  
  Server  
        Server響應報頭域包含了伺服器用來處理請求的軟體資訊。它和User-Agent請求報頭域是相對應的,前者傳送伺服器端軟體的資訊,後者傳送客戶端軟體(瀏覽器)和作業系統的資訊。下面是Server響應報頭域的一個例子:Server:   Apache-Coyote/1.1  
  WWW-Authenticate  
        WWW-Authenticate響應報頭域必須被包含在401(未授權的)響應訊息中,這個報頭域和前面講到的Authorization請求報頭域是相關的,當客戶端收到401響應訊息,就要決定是否請求伺服器對其進行驗證。如果要求伺服器對其進行驗證,就可以傳送一個包含了Authorization報頭域的請求,下面是WWW-Authenticate響應報頭域的一個例子:WWW-Authenticate:   Basic   realm="Basic   Auth   Test!"  
  從這個響應報頭域,可以知道伺服器端對我們所請求的資源採用的是基本驗證機制。
實體報頭  
 請求和響應訊息都可以傳送一個實體。一個實體由實體報頭域和實體正文組成,大多數情況下,實體正文就是請求訊息中的請求正文或者響應訊息中的響應正文。但是在傳送時,並不是說實體報頭域和實體正文要在一起傳送,例如:有些響應可以只包含實體報頭域。實體就好象我們寫的書信,在信中,我們可以寫上標題,加上頁號等,這部分就相當於是實體報頭域,而我們所寫的書信的內容,就相當於實體正文。前面說講的普通報頭、請求報頭、響應報頭我們可以看成是寫在信封上的郵編、接收者,傳送者等內容。  
  實體報頭定義了關於實體正文(例如:有無實體正文)和請求所標識的資源的元資訊。  
  所謂元資訊,是指描述其他資訊的資訊。  
   
  常用的實體報頭域:  
  Content-Encoding  
          Content-Encoding實體報頭域被使用作媒體型別的修飾符,它的值指示了已經被應用到實體正文的附加內容編碼,因而要獲得Content-Type報頭域中所引用的媒體型別,必須採用相應的解碼機制。Content-Encoding主要用語記錄文件的壓縮方法,下面是它的一個例子:Content-Encoding:   gzip。如果一個實體正文采用了編碼方式儲存,在使用之前就必須進行解碼。  
  Content-Language  
          Content-Language實體報頭域描述了資源所用的自然語言。Content-Language允許使用者遵照自身的首選語言來識別和區分實體。如果這個實體內容僅僅打算提供給丹麥的閱讀者,那麼可以按照如下的方式設定這個實體報頭域:Content-Language:   da。  
  如果沒有指定Content-Language報頭域,那麼實體內容將提供給所以語言的閱讀者。  
  Content-Length  
          Content-Length實體報頭域用於指明正文的長度,以位元組方式儲存的十進位制數字來表示,也就是一個數字字元佔一個位元組,用其對應的ASCII碼儲存傳輸。  
          要注意的是:這個長度僅僅是表示實體正文的長度,沒有包括實體報頭的長度。  
  Content-Type  
          Content-Type實體報頭域用語指明發送給接收者的實體正文的媒體型別。例如:  
  Content-Type:   text/html;charset=ISO-8859-1  
  Content-Type:   text/html;charset=GB2312  
  Last-Modified  
          Last-Modified實體報頭域用於指示資源最後的修改日期及時間。  
  Expires  
          Expires實體報頭域給出響應過期的日期和時間。通常,代理伺服器或瀏覽器會快取一些頁面。當用戶再次訪問這些頁面時,直接從快取中載入並顯示給使用者,這樣縮短了響應的時間,減少伺服器的負載。為了讓代理伺服器或瀏覽器在一段時間後更新頁面,我們可以使用Expires實體報頭域指定頁面過期的時間。當用戶又一次訪問頁面時,如果Expires報頭域給出的日期和時間比Date普通報頭域給出的日期和時間要早(或相同),那麼代理伺服器或瀏覽器就不會再使用快取的頁面而是從伺服器上請求更新的頁面。不過要注意,即使頁面過期了,也並不意味著伺服器上的原始資源在此時間之前或之後發生了改變。  
          Expires實體報頭域使用的日期和時間必須是RFC   1123中的日期格式,例如:  
  Expires:   Thu,   15   Sep   2005   16:00:00   GMT  
          HTTP1.1的客戶端和快取必須將其他非法的日期格式(也包括0)看作已過期。例如,為了讓瀏覽器不要快取頁面,我們也可以利用Expires實體報頭域,設定它的值為0,如下(JSP):response.setDateHeader("Expires",0);
 
除掉註釋的部分就是一個完整的包,向/user/tmpUpload.php上傳了一個檔案。  
  =========http頭==========  
  POST   /user/tmpUpload.php   HTTP/1.1  
  Content-Type:   multipart/form-data;   boundary=---------------------------7d53b9297030e  
  Content-Length:   1017  
   
  -----------------------------7d53b9297030e  
  Content-Disposition:   form-data;   name="upload";   filename="C:\Documents.and.Settings\hwy\桌面\attachment"  
  Content-Type:   p  
   
  11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111  
  -----------------------------7d53b9297030e--  
     
    ===========結束============