之前寫過一篇博客,說的如何python如何通過http下載文件,今天寫一篇博客來介紹如下,python如何通過request庫實現上傳文件
這里主要是解決multipart/form-data這種格式的文件上傳,基本現在http協議上傳文件基本上都是通過這種格式上傳
一、思路
一般情況下,如果我們往一個地址上傳文件,則必須要登陸,登陸成功后,拿到cookies,然后在上傳文件的請求攜帶這個cookies。
然后我們就需要通過瀏覽器在網站上傳文件,記得,這個時候抓包要使用fiddler工具,會更加保險,然后按照fiddler抓到包組裝我們的上傳文件的post請求
大家把握一個原則就是:在post請求中,用files參數來接受文件對象相關的參數,通過data/json參數接受post請求體的其他參數即可。
二、實現
1、使用requests.session()對象登陸網站,這里主要為了方便,下次直接用這個對象發送post上傳文件的請求即可,不需要我們在請求體中添加cookies
import requests
s = requests.session()
res1 = s.post(
url="http://10.222.222.7/src/welcome.php",
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cache-Control": "max-age=0",
"Connection": "keep-alive",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "10.222.222.7",
"Origin": "http://10.222.222.7",
"Referer": "http://10.222.222.7/src/welcome.php",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36"
},
data = {
"name": "admin",
"password": "admin",
"button": "登錄",
"opr": "login",
},
# 這里配置了代理,因為我的操作安裝了fiddler,這個你們沒有說一定要弄
proxies={
"http": "http://127.0.0.1:8888",
"https": "http://127.0.0.1:8888"
}
)

2、手動上傳,通過fiddler抓包,分析http請求的參數

上面是http請求的raw格式,我們一般會看webForms格式的http請求

3、分析完成后,我們可以看下代碼
import json
file = {
"sample_file": open("D:\\abdi\\37571.pcap", "rb"),
"Content-Type": "application/octet-stream",
"Content-Disposition": "form-data",
"filename" : "3757.pcap"
}
# #
res = s.post(
url="http://10.222.222.7/src/system_sample.php/system_sample/add",
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cache-Control": "max-age=0",
"Connection": "keep-alive",
# "Content-Type": "multipart/form-data",
"Host": "10.222.222.7",
"Origin": "http://10.222.222.7",
"Referer": "http://10.222.222.7/src/html.php/html/system_samples",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36"
},
files = file,
data = {
"sample_name" : "37571.pcap",
"owner_group" : "/data/atp/pcap/custom/test",
"type" : "1",
"sample_file_path" : "",
"description_file_path" : "",
# "description_file":""
},
proxies = {
"http":"http://127.0.0.1:8888",
"https":"http://127.0.0.1:8888"
}
)
這里有三個關鍵的地方
a、data參數,注意看k值和抓包中的對比


不同的網站的name的值可能不一樣,但是大部分大家都會用file,但是有時候開發人員也不會按照常規套路來做,所以我們不能想當然就認為是files。要通過抓包分析
這個值一般就是上傳后的文件的名稱;其他幾個參數的意義就不重要了,你要根據具體的情況分析組裝上傳就可以了
b、files參數,這里很關鍵,這里就是我們上傳的文件對象了


sample_file這個參數就代表文件文件對象

c、content-type參數,如果我們通過form-data的方式上傳文件,我們組裝post請求的時候,headers這個參數中一定不能要包括這個值,由requests庫幫添加這個元素
如果我們自作聰明,會導致上傳失敗的,這里非常重要!!!
大家可以看到,我在代碼中沒有傳遞content-type這個參數,但是抓包是有這個參數的,所以這個參數我們一定不能加

實際抓包有這個參數

4、實際上傳抓包驗證即可,和瀏覽器上傳略有不同,但是不影響上傳

