替代Python3.13废弃cgi.py的文件上传与请求处理实现
替代cgi.py实现GET/POST请求处理及文件上传(适用于Apache2 mod_cgi)
问题背景
由于cgi.py模块将在Python 3.13中被废弃,需替换原有处理GET、POST请求的代码,同时新增文件上传功能。以下是基于multipart库的可行实现方案,适配Apache2 mod_cgi环境。
实现步骤
1. 安装multipart库
执行以下命令安装依赖:
pip install multipart
2. 核心实现代码
#!/usr/bin/python3 # MIT许可证 # 版权所有 2023 BestInternetSearch.com Inc. # 特此免费授予任何获得本软件及相关文档文件(以下简称“软件”)副本的人,无限制地处理软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,并允许向其提供软件的人做出上述行为,但须符合以下条件: # 上述版权声明和本许可声明应包含在软件的所有副本或实质性部分中。 # 本软件按“原样”提供,无任何明示或暗示的担保,包括但不限于适销性、特定用途适用性和非侵权性的担保。在任何情况下,作者或版权持有人均不对因软件或软件的使用或其他交易而产生的任何索赔、损害或其他责任承担责任,无论是合同诉讼、侵权诉讼还是其他形式的诉讼。 import os import sys from html import escape import urllib from multipart import MultipartParser, MultiDict, parse_options_header forms, files = MultiDict(), MultiDict() class MyCGI(): _os_environ = [] _escape = True _data = {} def __init__(self, os_environ, escape=True): self._os_environ = os_environ self._escape = escape def FieldStorage(self): e = self._os_environ if 'REQUEST_METHOD' in e: if e['REQUEST_METHOD'] == 'GET': self._data = urllib.parse.parse_qs(e['QUERY_STRING']) elif e['REQUEST_METHOD'] == 'POST': if 'CONTENT_TYPE' in e: content_type, options = parse_options_header(e['CONTENT_TYPE']) if 'multipart/form-data' in content_type: boundary = options.get("boundary", "") if 'CONTENT_LENGTH' in e: content_length = int(os.environ.get("CONTENT_LENGTH", "-1")) stream = sys.stdin.buffer for part in MultipartParser(stream, boundary, content_length): if part.filename or not part.is_buffered(): files[part.name] = part elif 'application/x-www-form-urlencoded' in content_type: self._data = urllib.parse.parse_qs(sys.stdin.read(), keep_blank_values=True) def getvalue(self, arg_key, default=''): if arg_key in self._data: value = self._data[arg_key] if isinstance(value, list): if self._escape: return escape(self._data[arg_key][0]) else: return self._data[arg_key][0] else: if self._escape: return escape(value) else: return value else: return default
3. 使用示例
基本GET/POST参数获取
mycgi = MyCGI(os.environ) mycgi.FieldStorage() user = mycgi.getvalue('user') # 获取名为user的参数值,默认返回空字符串
文件上传测试与保存
先用curl模拟上传请求:
curl -F "text=default" -F "filename=@/home/computer/Desktop/aa.png" -F "filename=@/home/computer/Desktop/bb.png" http://example_website.com
再在代码中处理上传的文件:
# 获取所有名为filename的上传文件 filenames = files.getall('filename') # 逐个保存文件 for idx, file in enumerate(filenames): file.save_as(f"/home/computer/Desktop/file{idx}.png")
内容的提问来源于stack exchange,提问作者Stan S.
相关产品推荐
相关产品推荐

