Python 实现http server接收mutipart/form-data文件 方法2

Python 实现http server接收mutipart/form-data文件 方法2

    • [1 Server端代码](#1 Server端代码)
    • [2 测试](#2 测试)

1 Server端代码

以下代码亲测有效,仅适应于接收客户端上传的图片,其他文件未曾测试,作者主要应用于平时的自测工具。
说明1: 如有特殊需求,请自行更改,有意见,评论区留言。
说明2: 建议使用这个方法用于生产、成熟软件开发。Python 实现http server接收mutipart/form-data文件 方法1

python 复制代码
from dataclasses import replace
from http.server import HTTPServer, BaseHTTPRequestHandler
import json,os,re,chardet,posixpath,codecs
from urllib.parse import unquote

class Resquest(BaseHTTPRequestHandler):
    def do_POST(self):
        print("headers:", self.headers)
        print("command:",self.command)
        print("path:",self.path)
        
        bdy = self.headers.get_boundary()
        if not  bdy is None:
            print(" = in headers")
            boundary = self.headers['content-type'].split("=")[1]
            print("boundary:",boundary)
            if "Boundary" in boundary :
                print("parser image")
                self.deal_post_data()
            else :
                print("can't handle boundary")
        else :
             print(" = not in headers")
             req_datas = self.rfile.read(int(self.headers['content-length'])) 
             print("--------------------接受client发送的数据----------------")
             res1 = req_datas.decode('utf-8')
             res = json.loads(req_datas)
             print(res)
             #f = open('1.txt', 'w')
             #f.write(req_datas.decode())
             #f.close()
             #print(req_datas)
             print("--------------------接受client发送的数据完毕------------------")
             #data1 = {'bbb':'222'}
             #data = json.dumps(data1)
             #self.send_response(200)
             #self.send_header('Content-type', 'application/json')
             #self.end_headers()
             #self.wfile.write(data)

    def deal_post_data(self):
        boundary = self.headers["Content-Type"].split("=")[1].encode('ascii')
        print("boundary===", boundary)
        remain_bytes = int(self.headers['content-length'])
        print("remain_bytes===", remain_bytes)

        res = []
        line = self.rfile.readline()
        print("line=",line)
        bdarys = boundary.decode()
        bdarys = bdarys.replace(" ","")
        boundary = bdarys.encode()
        while boundary in line and str(line, encoding = "utf-8")[-4:] != "--\r\n":
            #line = self.rfile.readline()
            remain_bytes -= len(line)
            if boundary not in line:
                return False, "Content NOT begin with boundary"
            line = self.rfile.readline()
            remain_bytes -= len(line)
            print("line!!!==",str(line))    
            strLine = str(line)      
            fn = strLine.split(';') [2].replace(' filename=','')
            fn= fn[:-5]
            print("fn==",fn)
            if not fn:
                print("False, Can't find out file name...")
                return False, "Can't find out file name..."
            path = translate_path(self.path)
            print("path==",path)

            fname = fn
            #fname = fname.replace("\\", "\\\\")
            fname = self.str_to_chinese(fname)
            print("fname==",fname)
            
            fn = os.path.join(path, fname)
            print("SavefilePath==",fn)
            dirname = os.path.dirname(fn)
            if not os.path.exists(dirname):
                os.makedirs(dirname)
            line = self.rfile.readline()
            remain_bytes -= len(line)
            line = self.rfile.readline()
            # b'\r\n'
            remain_bytes -= len(line)
            try:
                out = open(fn, 'wb')
            except IOError:
                return False, "Can't create file to write, do you have permission to write?"

            pre_line = self.rfile.readline()
            print("pre_line", pre_line)
            remain_bytes -= len(pre_line)
            print("remain_bytes", remain_bytes)
            Flag = True
            while remain_bytes > 0:
                line = self.rfile.readline()
                #print("while line", line)
                
                if boundary in line:
                    remain_bytes -= len(line)
                    pre_line = pre_line[0:-1]
                    if pre_line.endswith(b'\r'):
                        pre_line = pre_line[0:-1]
                    out.write(pre_line)
                    out.close()
                    #return True, "File '%s' upload success!" % fn
                    res.append("File '%s' upload success!" % fn)
                    Flag = False
                    break
                else:
                    out.write(pre_line)
                    pre_line = line
            if pre_line is not None and Flag == True:
                out.write(pre_line)
                out.close()
                res.append("File '%s' upload success!" % fn)
            #return False, "Unexpect Ends of data."
        return True, res

    def str_to_chinese(self,var):
        not_end = True
        while not_end:
            start1 = var.find("\\x")
            # print start1
            if start1 > -1:
                str1 = var[start1 + 2:start1 + 4]
                print(str1)
                start2 = var[start1 + 4:].find("\\x") + start1 + 4
                if start2 > -1:
                    str2 = var[start2 + 2:start2 + 4]

                    start3 = var[start2 + 4:].find("\\x") + start2 + 4
                    if start3 > -1:
                        str3 = var[start3 + 2:start3 + 4]
            else:
                not_end = False
            if start1 > -1 and start2 > -1 and start3 > -1:
                str_all = str1 + str2 + str3
                # print str_all
                str_all = codecs.decode(str_all, "hex").decode('utf-8')

                str_re = var[start1:start3 + 4]
                # print str_all, "   " ,str_re
                var = var.replace(str_re, str_all)
        # print var.decode('utf-8')
        return var

def translate_path(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(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
        
if __name__ == '__main__':
    host = ('192.168.1.16', 18098)
    server = HTTPServer(host, Resquest)
    print("Starting server, listen at: %s:%s" % host)
    server.serve_forever()

2 测试

参见链接文章中的客户端测试方法进行测试。

如有其他需求或问题,烦请评论区留言。
Python 实现http server接收mutipart/form-data文件 方法1

相关推荐
niuniu_66627 分钟前
selenium应用测试场景
python·selenium·测试工具·单元测试·测试
满怀10151 小时前
Python扩展知识详解:lambda函数
开发语言·python
佚名涙2 小时前
go中锁的入门到进阶使用
开发语言·后端·golang
猫猫的小茶馆2 小时前
【PCB工艺】软件是如何控制硬件的发展过程
开发语言·stm32·单片机·嵌入式硬件·mcu·51单片机·pcb工艺
勘察加熊人3 小时前
wpf+c#路径迷宫鼠标绘制
开发语言·c#·wpf
蓝博AI3 小时前
基于卷积神经网络的眼疾识别系统,resnet50,efficentnet(pytorch框架,python代码)
pytorch·python·cnn
小黄人软件4 小时前
C# ini文件全自动界面配置:打开界面时读ini配置到界面各控件,界面上的控件根据ini文件内容自动生成,点保存时把界面各控件的值写到ini里。
开发语言·c#
牧歌悠悠5 小时前
【Python 算法】动态规划
python·算法·动态规划
Doris Liu.7 小时前
如何检测代码注入(Part 2)
windows·python·安全·网络安全·网络攻击模型
逢生博客7 小时前
阿里 FunASR 开源中文语音识别大模型应用示例(准确率比faster-whisper高)
人工智能·python·语音识别·funasr