Python 服务器 cgi.FieldStorage 解析 multipart/form-data

标签 python forms http post cgi

所以我一直在用 Python 编写一个简单的 Web 服务器,现在我正在尝试处理 multipart/form-data POST 请求。我已经可以处理 application/x-www-form-urlencoded POST 请求,但相同的代码不适用于多部分。如果看起来我误会了什么,请告诉我,即使是小事。另外,如果你们有任何关于改进我的代码的建议,也请告诉我 :) 谢谢!

当请求进来时,我首先对其进行解析,并将其拆分为标题字典和请求正文的字符串。然后我使用它们构建一个 FieldStorage 表单,然后我可以像字典一样处理它以提取数据:

requestInfo = ''
while requestInfo[-4:] != '\r\n\r\n':
    requestInfo += conn.recv(1)

requestSplit = requestInfo.split('\r\n')[0].split(' ')
requestType = requestSplit[0]

url = urlparse.urlparse(requestSplit[1])
path = url[2] # Grab Path

if requestType == "POST":
    headers, body = parse_post(conn, requestInfo)

    print "!!!Request!!! " + requestInfo
    print "!!!Body!!! " + body 
    form = cgi.FieldStorage(headers = headers, fp = StringIO(body), environ = {'REQUEST_METHOD':'POST'}, keep_blank_values=1)

这是我的 parse_post 方法:

def parse_post(conn, headers_string):
    headers = {}
    headers_list = headers_string.split('\r\n')

    for i in range(1,len(headers_list)-2):
        header = headers_list[i].split(': ', 1)
        headers[header[0]] = header[1]

    content_length = int(headers['Content-Length'])

    content = conn.recv(content_length)

    # Parse Content differently if it's a multipart request??

    return headers, content

因此对于 x-www-form-urlencoded POST 请求,我可以将 FieldStorage 表单视为字典,如果我调用,例如:

firstname = args['firstname'].value
print firstname

它会起作用的。但是,如果我改为发送多部分 POST 请求,它最终不会打印任何内容。

这是 x-www-form-urlencoded 请求的主体: 名=测试&姓=rwar

这是多部分请求的主体: --070f6a3146974d399d97c85dcf93ed44 Content-Disposition:表单数据;名字=“姓氏”;文件名=“姓氏”

rwar --070f6a3146974d399d97c85dcf93ed44 Content-Disposition:表单数据;名字=“名字”;文件名="名字"

测试 --070f6a3146974d399d97c85dcf93ed44--

那么问题来了,如果是多部分请求,我是否应该手动解析 parse_post 中数据的正文?

或者是否有我需要/可以用来解析多部分正文的方法?

还是我完全做错了?

再次感谢,我知道这是一篇很长的文章,但我想确保我的问题是全面的

最佳答案

所以我解决了我的问题,但是以一种完全 hacky 的方式。

结束了手动解析请求的主体,这是我写的代码:

if("multipart/form-data" in headers["Content-Type"]):
    data_list = []
    content_list = content.split("\r\n\r\n")
    for i in range(len(content_list) - 1):
        data_list.append("")

    data_list[0] += content_list[0].split("name=")[1].split(";")[0].replace('"','') + "="

    for i,c in enumerate(content_list[1:-1]):
        key = c.split("name=")[1].split(";")[0].replace('"','')
        data_list[i+1] += key + "="
        value = c.split("\r\n")
        data_list[i] += value[0]

    data_list[-1] += content_list[-1].split("\r\n")[0]

    content = "&".join(data_list)

如果有人无需手动解析正文就可以解决我的问题,请告诉我!

关于Python 服务器 cgi.FieldStorage 解析 multipart/form-data,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21997912/

相关文章:

python - 为什么你永远不应该重新加载模块?

python - tkinter 和 time.sleep

javascript - 多个复选框 > 至少应显示一条必填项,否则会显示错误消息

python - Python 中的有序字典 : add to MongoDB

python - Cassandra 3.7与Python, 'NoneType'对象没有属性 'encode_message'

php - 通过 PHP/Curl 将 HTML 表单传递到 JSP 页面...传递没有发生

asp.net-mvc - 带有表单和列表的 MVC 3 : default model binder and EditorFor

c# - 通过 ASP.NET C# 发送 HTTP 请求

ruby-on-rails - 正确执行 redirect_to :back in Ruby on Rails when referrer is not available

javascript - 如何在客户端发出自定义 "POST"请求?