python使用requests庫通過proxy代理post上傳文件

python使用requests庫通過proxy代理post上傳文件

python通過http post的方式上傳文件到服務器有多種方式,使用urllib2庫,poster庫和requests庫均可實現。此處由於環境的限制,使用requests庫來實現。先上代碼,我使用的是python2進行的編寫

import requests
import json

f = open("./abc", "rb")
url = 'http://100.11.12.13:8989/upload'
files = {'file' : f } 
headers = { "Host" : "100.11.12.13:8989" }
proxy =  { 'http' : "192.168.1.156:8012"}
post_data = {}
post_data["name"] = "bob"
data = json.dumps(post_data).encode("utf-8")

r = request.post(url,proxies=proxy,data=data,files=files,headers=headers)
print(r.text)
f.close();

此處主要涉及如下方面

  1. 文件上傳
    通過post接口files參數上傳,參數爲字典結構,file爲key值,f打開的句柄表示要上傳的文件內容,此處使用了最簡潔的形式,根據博客 requests上傳多個文件 ,官方 推薦如下結構
{
  "field1" : ("filename1", open("filePath1", "rb")),
  "field2" : ("filename2", open("filePath2", "rb"), "image/jpeg"),
  "field3" : ("filename3", open("filePath3", "rb"), "image/jpeg", {"refer" : "localhost"})
}

在上面的最簡模式中 filename 就是filepath中的文件名。該接口參數字典可以以這種方式,支持同時上傳不同key值的多個文件。

  1. 代理設置
proxy =  { 'http' : "192.168.1.156:8012"}

該行是設置目的代理爲 192.168.1.156的8012端口上的服務,我在這個位置部署了一臺windows上的nginx服務器。對上傳請求做代理轉發。此處的 key值指定的是協議的類型,即使是http,也不限制是80端口,實際上我上述的請求服務器目的端口就不是80端口,對應的需要通過https協議進行上傳時,需將key值指定爲 https ,同時可能需要設置字段,
verify=False.

  1. 頭部信息設置
    但上述的設置仍然無法完成通過proxy代理進行post文件的上傳,我是在python 2.7.3 版本,會提示對應頁面無法訪問,通過抓包發現,雖然 url中請求的目的端口是8989端口,但是Host中的信息是隻有100.11.12.13,即不含有端口的信息,而nginx在進行代理轉發時,是依賴Host中的信息進行代理轉發的,如下
        location / {
            proxy_pass http://$http_host$request_uri;
        }

此處應是該版本requests庫的實現缺陷,故而需要在headers中再指定,headers = { “Host” : “100.11.12.13:8989” }。才能夠再nginx代理轉發時完成轉發。

  1. nginx代理配置
    nginx代理除了完成上述配置外,因post上傳內容可能較大,可能返回nginx 413錯誤,即Request Entity Too large,仍然需要在http模塊中增加 client上傳的body的配置信息如下:
http {
...
    client_max_body_size 100M;
...
}

client_max_body_size該值默認爲1MB,爲請求正文的允許大小,判斷的是Content-Length字段的值。

參考

http://cn.python-requests.org/zh_CN/latest/user/quickstart.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章