zoukankan      html  css  js  c++  java
  • 关于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)

    这样文件名和文件都传过去了。

  • 相关阅读:
    java代码终于过百行了
    团队建设中人员流失的问题
    将析构函数设置为虚函数,并且析构函数可以为纯虚函数
    J2EE学习笔记——JSP使用Fckeditor
    Android ListView的getview()中position错位 重复调用(position重复调用)
    修正Thinkphp 3.2 分页Page类以支持URL路由
    ThinkPHP中_after_update、_before_update等的用法
    ThinkPHP跨控制器调用方法
    Thinkphp 查询条件 and 和 or同时使用即复合查询
    layer弹出图片的问题
  • 原文地址:https://www.cnblogs.com/marszhw/p/10722995.html
Copyright © 2011-2022 走看看