所以我一直在用Python编写一个简单的Web服务器,现在我正在尝试处理multipart / form-data POST请求。我已经可以处理application / x-www-form-urlencoded的POST请求,但相同的代码不适用于multipart。如果看起来我误解了什么,请打电话给我,即使这是一个小问题。如果你们有任何关于使我的代码更好的建议,请告诉我:)谢谢!
当请求进入时,我首先解析它,并将其拆分为标题字典和请求正文的字符串。我使用它们然后构造一个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请求的正文: 姓名= TEST&安培;姓= rwar
这是多部分请求的正文: --070f6a3146974d399d97c85dcf93ed44 内容处理:表格数据; NAME = “姓氏”;文件名= “姓氏”
rwar --070f6a3146974d399d97c85dcf93ed44 内容处理:表格数据; NAME = “姓名”;文件名= “姓名”
TEST --070f6a3146974d399d97c85dcf93ed44 -
所以这就是问题,如果它是一个多部分请求,我应该手动解析parse_post中数据的正文吗?
或者我需要/可以使用哪种方法来解析多部分体?
或者我完全错了吗?
再次感谢,我知道这是一个很长的阅读,但我想确保我的问题是全面的
答案 0 :(得分:2)
所以我解决了我的问题,但是以一种完全黑客的方式。
结束手动解析请求的正文,这是我写的代码:
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)
如果有人仍然可以解决我的问题而无需手动解析身体,请告诉我!
答案 1 :(得分:0)
有一个streaming-form-data项目,它提供了一个Python解析器来解析multipart/form-data
编码的数据。它旨在允许以块的形式解析数据,但由于没有强制执行块大小,您可以立即传递整个输入,它应该完成工作。它应该可以通过pip install streaming_form_data
安装。
以下是源代码 - https://github.com/siddhantgoel/streaming-form-data
文档 - https://streaming-form-data.readthedocs.io/en/latest/
免责声明:我是作者。当然,如果您遇到错误,请创建一个问题。 :)