python 使用requests post請求發送form-data類型數據


某些post接口,需要發送multipart/form-data類型的數據,如何使用python requests來模擬這種類型的請求發送呢?

 

根據http/1.1 rfc 2616的協議規定,我們的請求方式有OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE等。

http協議規定以ASCII碼傳輸,建立在tcp,ip協議之上的引用規范。規范內容把http請求分成3個部分:狀態行,請求頭,請求體。所有的方法,實現都是圍繞如何使用和組織這三部分來完成了,萬變不離其宗。

post請求有兩種編碼格式:application/x-www-form-urlencoded 和 multipart/form-data

application/x-www-form-urlencoded

  • application/x-www-form-urlencoded 常用在前端表單提交時,參數格式為:key=value&key=value。
  • 如果參數中有特殊字符,則要進行url編碼,編碼格式就是application/x-www-form-urlencoded(規則:將鍵值對的參數用&連接起來;有空格轉換為+加號;有特殊符號轉換為ASCII HEX值)。
        如:參數值中有&,需要轉換為ASCII HEX值%26,對應ASCII中38位置的&。
  • application/x-www-form-urlencoded是瀏覽器默認的編碼格式。對於Get請求,是將參數轉換為?key=value&key=value格式,連接到url后。

 

 

multipart/form-data

multipart/form-data格式不僅可以傳輸參數,還可以傳輸文件。也是在post基礎上演變而來的,具體如下:

  1. multipart/form-data的基礎方式是post,即基於post請求來實現的。
  2. multipart/form-data與普通post方法的不同之處在於請求頭和請求體。
  3. multipart/form-data的請求頭必須包含一個特殊的頭信息:Content-Type,其值也必須為multipart/form-data;同時還需要規定一個內容分割用於分割請求體中不同參數的內容。
    具體的頭信息如下:Content-Type: multipart/form-data; boundary=${bound}
  4. multipart/form-data的請求體也是一個字符串,和普通post請求的不同之處在於它的構造方式。普通post請求是簡單的鍵值對連接,而multipart/form-data則是添加了分隔符、參數描述信息等內容的構造體。

 

 

 

關於boundary:

  • 上面說到普通post請求使用 & 來分隔參數,那服務器使用multipart/form-data格式接收POST請求時,使用何種方式來分割參數的呢?答案是boundary。
  • 由上圖可以發現,HTTP的Body中使用兩個短橫線”–”加上boundary字符串作為不同參數的分割,而且不管是值參數(Value)還是文件參數(File)在Boundary內部都有自己的描述信息,並不是URL參數的簡單移動。
    並且在結束的時候,不僅前綴要加雙短橫線,后綴也要加,代表結束。

boundary快問快答:

Q:boundary的值是用戶可以自由定義的嗎?
A:是的,但為了避免和正常文本重復了,盡量要使用復雜一點的內容。

Q:boundary的作用?
A:分割參數,類似於普通post請求中的 & 

使用python發送multipart/from-data類型數據

有兩種方式:

  1. 手動組建form-data並修改headers
  2. 通過files參數傳遞form-data,推薦此種方式,這里只說這種方式

在官方網站上,requests模擬一個表單數據的格式如下:

files = {{name}: (<filename>, <file object>,<content type>, <per-part headers>)}

這一行模擬出來的post數據為:

Content-Disposition: form-data; name={name};filename=<filename>
Content-Type: <content type>

<file object>
--boundary

注:如果filename 和 content-Type不寫,那么響應模擬post的數據就不會有二者。

 

通過上述說明,我們可以構造出files后直接post請求發送即可:

files = {
'schoolId': (None, -1),
'schoolName': (None, ""),
"reward": (None, 5),
"publishText": (None, "測試測試"),
"tags": (None, 1),
'image': ('image.jpg', open('%s/resource/upload_images/image.jpg' % PATH_DIR, 'rb'), 'application/octet-stream')
}
response = requests.post(url, files=files)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM