關於python 的http 日常操作


20190430更新

重要的內容放在最前面,本地調試好的程序要放公網服務器上,怎么就不好用了呢?服務也啟動了,但是就是訪問不了,

排除了防火牆的問題,后來對比了node app的啟動方式,netstat -ntpl | grep 7777

找到了靈感,原來只要這么改一下就好了

before :host = ('localhost', 7777)
after:host = ('', 7777)

Http,互聯網的基礎

.net ,java(springboot),node.js,python 都能非常方便的實現http服務。

現在服務器后台跑着pytorch的模型,想着還是用python來處理文件上傳請求吧,雖然其他語言之間的互相調用也沒問題。

聽說python的http服務對多線程支持不夠,而且穩定性未知,但是不試試看怎么知道。

下面貼出代碼,需要用的同志們隨便用,因為我也是網上拼湊出來的代碼。

服務器端:HttpServer.py

#! -*- coding:utf-8 -*-
__author__ = 'marszhang'
import cgi
import os
import http.server
import json
# import urlparse
import urllib.parse
from http.server import HTTPServer, BaseHTTPRequestHandler

LOCAL_FOLDERS = [
"D:\\SIFT"
]
BASE_URL = "http://140.143.184.29"
data = {'result': 'this is a result','test': 'this is a test'}
host = ('localhost', 7777)
data_json = json.dumps({'key1':'value1','key2':'value2'}) #dumps:將python對象解碼為json數據

class WebRequestHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
print("Request for '%s' received." % self.path)
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(data).encode())
def do_POST(self):
enc = "UTF-8"
path = str(self.path)
#獲取POST請求的一種方式,首先受到length,然后通過self.rfile里讀出該長度的數據
# length = int(self.headers["content-length"]) # 獲取除頭部后的請求參數的長度
# datas = urllib.parse.parse_qs(self.rfile.read(length), keep_blank_values=1) # 獲取請求參數數據,請求數據為json字符串
# print(datas)
if path == "/data":
# pass(可以添加對參數的邏輯處理)
# 以下是返回報文
self.send_response(200) # 返回狀態碼
self.send_header("Content-type", "text/html;charset=%s" % enc) # 返回響應頭內容
self.end_headers() # 返回響應頭結束
buf = {"status": 0, # 返回包體數據
"data": {"filepath": "返回成功"}}
#這里一定要加encode(),不然會報錯,bytes<-> str轉換的錯,bytes和str的互轉有三種方式,# s.encode(encoding="utf-8")
self.wfile.write(json.dumps(buf).encode()) # 發送json格式的返回包體
# 上傳圖片
if path == "/upload":
form = cgi.FieldStorage(
fp=self.rfile,
headers=self.headers,
environ={'REQUEST_METHOD': 'post',
'CONTENT_TYPE': self.headers['Content-Type']
}
)
datas = form['file'].value # 獲取上傳文件內容
fname = self.headers["filename"]
fn = os.path.join("D:\\study\\", fname) # 生成文件存儲路徑
outf = open(fn, 'wb') # 寫打開文件
outf.write(datas) # 將接收到的內容寫入文件
outf.close() # 關閉文件
self.send_response(200)
self.send_header("Content-type", "text/html;charset=%s" % enc)
self.send_header("test", "This is test!")
self.end_headers()
buf = {"status": 0,
"data": {
"msg": u"上傳成功"}}
self.wfile.write(json.dumps(buf))
if __name__ == '__main__':
try:
server = HTTPServer(host, WebRequestHandler)
print("Starting server, listen at: %s:%s" % host)
server.serve_forever()
except KeyboardInterrupt:
print('shutdong doen server')
server.socket.close()

客戶端:Httpclient.py

#coding=utf-8
import requests
url = "http://localhost:7777/upload"
path = "D:\\test\\1\\20190329180730.png"
print(path)
files = {'file': open(path, 'rb')}
headers = {"filename":"20190329180730.png"}
r = requests.post(url, files=files,headers=headers)
print(r.url)
print(r.text)

需要注意的是,python通過requests發送post請求,通常可以有以下三種方式,當然不用客戶端來發請求,用postman來發請求也可以,

A:application/x-www-form-urlencoded ==最常見的post提交數據的方式,以form表單形式提交數據

data  =  { 'key1' : 'value1' , 'key2' : 'value2' }
= requests.post(url,data)

B:application/json    ==以json格式提交數據

data_json  =  json.dumps({ 'key1' : 'value1' , 'key2' : 'value2' })    #dumps:將python對象解碼為json數據
r_json  =  requests.post(url,data_json)

C:multipart/form-data  ==一般使用來上傳文件(較少用)

files  =  { 'file' : open ( 'E://report.txt' , 'rb' )}
=  requests.post(url,files = files)

 

此時,如果需要傳一些其他參數,也有很多種辦法,這篇博文已經講得非常全面了,https://www.cnblogs.com/puresoul/p/7488700.html

有八種

  1、帶數據的post ->見上面例子A

  2、帶header的post   ->見下面例子

  3、帶json的post ->見上面例子B

  4、帶參數的post

      params = {'key1':'params1','key2':'params2'}
      r = requests.post(url,params=params)

  5、普通文件上傳 ->見上面例子C

  6、定制化文件上傳

     files = {'file':('test.png',open('test.png','rb'),'image/png')}
     r = requests.post(url,files=files)

  7、多文件上傳  

     files = [('file1',('test.txt',open('test.txt', 'rb'))),
         ('file2', ('test.png', open('test.png', 'rb')))]
     r = requests.post(url,files=files)

  8、流式上傳

 
        
     with open( 'test.txt' ) as f:
       r = requests.post(url,data = f)

 

我習慣把參數放到header里,比如

files = {'file': open(path, 'rb')}
headers = {"filename":"20190329180730.png"}
r = requests.post(url, files=files,headers=headers)

這樣文件名和文件都傳過去了。

 


免責聲明!

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



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