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

相关推荐
咖啡の猫2 小时前
Python字典推导式
开发语言·python
曹文杰15190301122 小时前
2025 年大模型背景下应用统计本科 计算机方向 培养方案
python·线性代数·机器学习·学习方法
leiming62 小时前
C++ vector容器
开发语言·c++·算法
SystickInt3 小时前
C语言 strcpy和memcpy 异同/区别
c语言·开发语言
Wulida0099913 小时前
建筑物表面缺陷检测与识别:基于YOLO11-C3k2-Strip模型的智能检测系统
python
CS Beginner3 小时前
【C语言】windows下编译mingw版本的glew库
c语言·开发语言·windows
FJW0208143 小时前
Python_work4
开发语言·python
大学生资源网3 小时前
java毕业设计之儿童福利院管理系统的设计与实现(源码+)
java·开发语言·spring boot·mysql·毕业设计·源码·课程设计
JasmineWr3 小时前
JVM栈空间的使用和优化
java·开发语言
爱笑的眼睛114 小时前
从 Seq2Seq 到 Transformer++:深度解构与自构建现代机器翻译核心组件
java·人工智能·python·ai