You need to enable JavaScript to run this app. 基于Python http.server模块实现POST文件上传功能的问题求解
优惠活动
大模型
产品
解决方案
定价
更多

基于Python http.server模块实现POST文件上传功能的问题求解

问题解决与代码优化方案

一、self.rfile.readlines() 卡住的根因与解决方案

卡住的核心原因是HTTP/1.1默认启用长连接,self.rfile是绑定到TCP套接字的输入流,readlines()方法会持续等待流结束信号,只有当浏览器主动断开连接(比如关闭标签页)才会停止阻塞,返回已读取的内容。
正确处理方式:

  • 先从请求头中获取Content-Length字段,仅读取指定长度的请求体,避免无限等待
  • 不要手动正则解析multipart格式,直接用Python内置的cgi.FieldStorage工具类处理表单上传,自动拆分字段、提取文件名和文件内容,避免边界匹配错误导致的文件损坏问题。

二、do_POST() 正确实现示例

import os
import cgi
from http.server import SimpleHTTPRequestHandler

class SimpleHTTPRequestHandlerWithUpload(SimpleHTTPRequestHandler):
    # 已实现的list_directory方法此处省略,仅需保证表单enctype为multipart/form-data、method为POST即可
    def do_POST(self):
        try:
            # 解析表单数据
            form = cgi.FieldStorage(
                fp=self.rfile,
                headers=self.headers,
                environ={'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': self.headers['Content-Type']}
            )
            
            # 获取上传文件字段,假设表单中文件input的name属性为upload_file
            upload_item = form['upload_file']
            if not upload_item.filename:
                self.send_error(400, "No file selected for upload")
                return
            
            # 安全处理文件名:仅保留文件名主体,防止路径遍历攻击
            filename = os.path.basename(upload_item.filename)
            save_path = os.path.join(os.getcwd(), filename)
            
            # 写入文件
            with open(save_path, 'wb') as f:
                f.write(upload_item.file.read())
            
            # 校验上传结果
            upload_size = upload_item.length
            saved_size = os.path.getsize(save_path)
            if upload_size != saved_size:
                os.remove(save_path)
                self.send_error(500, "File upload failed: size mismatch")
                return
            
            # 上传成功后重定向回目录页,避免用户刷新重复提交
            self.send_response(303)
            self.send_header('Location', self.path)
            self.end_headers()
        except Exception as e:
            self.send_error(500, f"Upload error: {str(e)}")

三、其他代码优化建议

  • 安全加固:除文件名路径过滤外,可新增允许上传的文件后缀白名单、单文件大小上限限制,避免恶意上传可执行文件或超大文件占用磁盘
  • 重名文件处理:当前目录存在同名文件时,可自动给文件名加序号后缀(如a.jpg改为a_1.jpg),避免直接覆盖已有文件
  • 并发能力优化:默认http.server是单线程模式,多个上传请求并发时会发生阻塞,可继承ThreadingHTTPServer实现多线程处理,提升并发承载能力
  • 交互体验优化:可在目录页新增上传成功/失败的提示信息,不要仅返回纯HTTP错误码
  • 权限控制:如果服务需要部署在公网,需新增身份校验逻辑,避免未授权用户随意上传文件

内容的提问来源于stack exchange,提问作者m00nlightsh4dow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 08:45:02