在Python3中处理文件上传的代码是什么,以一种很好的方式取代cgi.py,当它在3.13中弃用时



我正在尝试替换cgi.py模块代码,因为它将在Python 3.13中被弃用。代码处理get和post方法,但是,我希望它也能够处理文件上传,什么代码会做到这一点?

:我已经回答了我自己的问题,与Apache2 mod_cgi工作,并提供了使用multipart的代码。

首先,从https://github.com/defnull/multipart

安装pip包multipart
pip install multipart

接下来,这是我当前的代码。

#!/usr/bin/python3
# The MIT License
# Copyright 2023 BestInternetSearch.com Inc.
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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 e['CONTENT_TYPE']:
if 'boundary' in e['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
if 'application/x-www-form-urlencoded' in e['CONTENT_TYPE']:
self._data = urllib.parse.parse_qs(str(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 == True:
return escape(self._data[arg_key][0])
else:
self._data[arg_key][0]
else:
if self._escape == True:
return escape(value)
else:
return value
else:
return default 

用法:

mycgi = MyCGI(os.environ)
mycgi.FieldStorage()
user = mycgi.getvalue('user')      
And uploading files something like:
curl -F "text=default" -F "filename=@/home/computer/Desktop/aa.png" -F "filename=@/home/computer/Desktop/bb.png" http://example_website.com
filenames = files.getall('filename')
for x, file in enumerate(filenames):
file.save_as(f"""/home/computer/Desktop/file{x}.png""")

http浏览器上传的文件被post为multipart-form-data。有几个库支持解析这些数据,例如:

  • 多部分
  • streaming-form-data
  • requests-toolbelt的MultipartDecoder
  • python-multipart

然而,你应该考虑重构你的应用程序,删除CGI并使用一个通用的和受支持的web框架。

更新:下面是一个非常基本的cgi脚本,它使用python-multipart包从multipart表单数据中提取有关字段和文件的信息:

#!/usr/bin/python3
import os
import sys
import multipart as mp

print("Content-Type: text/htmlnn")
print("<!doctype html>n")
# callbacks
def on_field(field):
print(f"Parsed field: {field.field_name} with value {field.value}<br>")
def on_file(file):
print(f"Parsed file: {file.field_name} with file name {file.file_name} and size {file.size}<br>")
# get header info
headers = {'Content-Type': os.environ['CONTENT_TYPE']}
if 'HTTP_X_FILE_NAME' in os.environ:
headers['X-File-Name'] = os.environ['HTTP_X_FILE_NAME']
if 'CONTENT_LENGTH' in os.environ:
headers['Content-Length'] = os.environ['CONTENT_LENGTH']
# parse the form
mp.parse_form(headers, sys.stdin.buffer, on_field, on_file)
print("Donen")

相关内容

  • 没有找到相关文章

最新更新