前面我們通過 post 請求發送的是文本內容,也就是 ASCII 字符。如果需要發送文件到服務器,比如上傳圖片、視頻等,就需要發送二進制數據。
一般上傳文件使用的都是Content-Type: multipart/form-data;
數據類型,可以發送文件,也可以發送相關的消息體數據。
使用 requests 上傳文件的基本步驟:
- 構造文件數據,通過 open 函數以二進制方式打開文件
- 構造相關數據
- 發送請求,將文件數據以 files 參數傳入,其他消息體數據通過 data或 json 傳入
requests 官方文檔上給出的示例如下:
>>> url = 'http://httpbin.org/post'
>>> files = {'file': open('report.xls', 'rb')} # => 直接通過open函數打開文件并將文件對象存在字典中
>>> r = requests.post(url, files=files)
>>> r.text
{
...
"files": {
"file": "<censored...binary...data>"
},
...
}
# 你可以顯式地設置文件名,文件類型和請求頭:
>>> url = 'http://httpbin.org/post'
>>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})} # => 打開上傳文件并且加入文件相關參數
>>> r = requests.post(url, files=files)
>>> r.text
{
...
"files": {
"file": "<censored...binary...data>"
},
...
}
我想大家雖然能看懂,但是依然會略顯懵逼。這里我還是以 showdoc 中的文件上傳為例為大家演示一下:
showdoc 中的文件上傳位于接口文檔的編輯頁面。
我們任意選擇一張圖片上傳,并抓包查看:
在原始中看到了相關的內容,包括 Content-Type,圖片信息等(切換到 Raw 的時候會比較卡)。Raw 中始終是查看請求內容最全面的地方,只是這里會顯示二進制的圖片內容,會比較卡。所以第一次我們看一下 Raw 即可。以后直接在 WebForms 中查看,需要的數據在那里都可以看到。
注意其中的
name="editormd-image-file"
,需要用此 name 為服務器指定文件對象。
好,接下來我們參考官方文檔上的方式模擬:
from urllib import parse
from pprint import pprint
import requests
host = 'http://127.0.0.1'
user = {
'username': 'showdoc',
'password':'123456'
}
s = requests.Session() # => 會話對象
# 登錄
login_url = parse.urljoin(host, '/showdoc/server/index.php?s=/api/user/login')
lr = s.post(login_url, data=user)
pprint(lr.json())
# 上傳圖片
upload_url = parse.urljoin(host,'http://127.0.0.1/showdoc/server/index.php?s=/api/page/uploadImg')
# 構造圖片數據,這里必須要填上圖片相關參數
file = {
'editormd-image-file': open(r'D:\data\1.png', 'rb'), # => 用name指定文件
'Content-Disposition': 'form-data',
'Content-Type': 'image/png',
'filename':'1.png'
}
ur = s.post(upload_url, files=file) # => 注意這里,參數名是 files
pprint(ur.json())
如果你遇到其他情況需要上傳文件的同時傳輸其他表單數據,直接和之前的 post 請求一樣,通過字典構造數據并通過 data 參數傳遞即可。
>>> r = s.post(upload_url, files=file, data=data) # => 包括url參數,headers,cookies都可以一起傳遞
警告
我們強烈建議你用二進制模式(binary mode)打開文件。這是因為 Requests 可能會試圖為你提供 Content-Length header,在它這樣做的時候,這個值會被設為文件的字節數(bytes)。如果用文本模式(text mode)打開文件,就可能會發生錯誤。