python HTTP服务端使用BaseHTTPServer、客户端urllib2.Request

服务端,继承HTTPServer,BaseHTTPRequestHandler类

处理post请求数据,交给后端,并发送响应信息。

参考:

https://blog.csdn.net/zhuyu_deng/article/details/38223207

https://www.cnblogs.com/findumars/p/6375541.html

#!/usr/bin/env python
 
"""Simple HTTP Server With Upload.
This module builds on BaseHTTPServer by implementing the standard GET
and HEAD requests in a fairly straightforward manner.
"""
 
 
__version__ = "0.1"
__all__ = ["SimpleHTTPRequestHandler"]
__author__ = "caitian"
__home_page__ = "https://www.cnblogs.com/caitian"
 
import os
import posixpath
import BaseHTTPServer
from  BaseHTTPServer import HTTPServer,BaseHTTPRequestHandler
import urllib
import time
import re
import random
import json
from TitleHandler import TitleHandler 

def tokenizer(iterator):
    TOKENIZER_RE = re.compile(r"[^\s]+", re.UNICODE)
    for value in iterator:
        yield TOKENIZER_RE.findall(value)


class MsParserServer(BaseHTTPServer.BaseHTTPRequestHandler):
 
    """Simple HTTP request handler with GET/HEAD/POST commands.
    This serves files from the current directory and any of its
    subdirectories.  The MIME type for files is determined by
    calling the .guess_type() method. And can reveive file uploaded
    by client.
    The GET/HEAD/POST requests are identical except that the HEAD
    request omits the actual contents of the file.
    """
 
    server_version = "SimpleHTTPWithUpload/" + __version__
     
 
    def do_POST(self):
        """Serve a POST request."""
        flag, path = self.deal_post_data()
        if flag:
            req_dic = {"req_type":"type_doc", \
               "file_link": path}
            datas = json.dumps(req_dic)
            tt_obj = TitleHandler()
            req = tt_obj.titletree(datas)
        else:
            req = {"req": "failed"}
        self.send_response(200)
        self.send_header("Content-type","json")
        self.end_headers()
        self.wfile.write(json.dumps(req))

 
    def deal_post_data(self):
        boundary = self.headers.plisttext.split("=")[1]
        remainbytes = int(self.headers['content-length'])
        #print self.rfile.read(remainbytes)
        line = self.rfile.readline()
        print line
        remainbytes -= len(line)
        if not boundary in line:
            return (False, "Content NOT begin with boundary")
        line = self.rfile.readline()
        remainbytes -= len(line)
        print line
        fn = re.findall(r'Content-Disposition.*name="file"; filename="(.*)"', line)
        if not fn:
            return (False, "Can't find out file name...")
       
        path = self.translate_path(self.path)
        fn = os.path.join(path, fn[0])
        fn = fn.split('/')[:-1]
        path_cut = ""
        for item in fn:
            path_cut+=item+'/'
        fn = path_cut + "%d_%d.docx" % (int(time.time()), random.randint(1,10000))
        print fn
       
        line = self.rfile.readline()
        remainbytes -= len(line)
        line = self.rfile.readline()
        remainbytes -= len(line)
        try:
            out = open(fn, 'wb')
        except IOError:
            return (False, "Can't create file to write, do you have permission to write?")
                
        preline = self.rfile.readline()
        remainbytes -= len(preline)
        while remainbytes > 0:
            line = self.rfile.readline()
            remainbytes -= len(line)
            if boundary in line:
                preline = preline[0:-1]
                if preline.endswith('\r'):
                    preline = preline[0:-1]
                out.write(preline)
                out.close()
                return (True, fn)
            else:
                out.write(preline)
                preline = line
        return (False, None)

    def translate_path(self, path):
        """Translate a /-separated PATH to the local filename syntax.
        Components that mean special things to the local file system
        (e.g. drive or directory names) are ignored.  (XXX They should
        probably be diagnosed.)
        """
        # abandon query parameters
        path = path.split('?',1)[0]
        path = path.split('#',1)[0]
        path = posixpath.normpath(urllib.unquote(path))
        words = path.split('/')
        words = filter(None, words)
        path = os.getcwd()
        for word in words:
            drive, word = os.path.splitdrive(word)
            head, word = os.path.split(word)
            if word in (os.curdir, os.pardir): continue
            path = os.path.join(path, word)
        return path

def test(port):
    http_server =HTTPServer(('', int(port)), MsParserServer)
    http_server.serve_forever()
 
if __name__ == '__main__':
    test(8006)

客户端post请求doc二进制数据,上传表单

需要安装poster模块

参考https://www.cnblogs.com/yu-zhang/p/3643528.html

#!/bin/python
#encoding=utf8

import os
import sys
import json
import logging
import time
import random
import re
from datetime import datetime
import json,urllib2
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers

reload(sys)  
sys.setdefaultencoding('utf8')

path = "data/K0001-A.docx"
url='http://192.168.2.42:8006'
# 在 urllib2 上注册 http 流处理句柄
register_openers()

# "file" 是参数的名字,一般通过 HTML 中的 <input> 标签的 name 参数设置

# headers 包含必须的 Content-Type 和 Content-Length
# datagen 是一个生成器对象,返回编码过后的参数,这里如果有多个参数的话依次添加即可
datagen, headers = multipart_encode({"file":open(path, "rb")})

# 创建请求对象
request = urllib2.Request(url, datagen, headers)
# 实际执行请求并取得返回
print urllib2.urlopen(request).read()