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

相关推荐
Tansmjs4 分钟前
使用Python自动收发邮件
jvm·数据库·python
m0_561359676 分钟前
用Python监控系统日志并发送警报
jvm·数据库·python
橘子师兄7 分钟前
C++AI大模型接入SDK—ChatSDK封装
开发语言·c++·人工智能·后端
idwangzhen20 分钟前
GEO优化系统哪个功能强大
python·信息可视化
上天_去_做颗惺星 EVE_BLUE22 分钟前
Docker高效使用指南:从基础到实战模板
开发语言·ubuntu·docker·容器·mac·虚拟环境
2401_8576835423 分钟前
C++中的原型模式
开发语言·c++·算法
s1hiyu32 分钟前
C++动态链接库开发
开发语言·c++·算法
(❁´◡`❁)Jimmy(❁´◡`❁)33 分钟前
CF2188 C. Restricted Sorting
c语言·开发语言·算法
星火开发设计38 分钟前
C++ 预处理指令:#include、#define 与条件编译
java·开发语言·c++·学习·算法·知识
许泽宇的技术分享40 分钟前
第 1 章:认识 Claude Code
开发语言·人工智能·python