Forms Python3中的cgi.parse_多部分函数抛出TypeError

Forms Python3中的cgi.parse_多部分函数抛出TypeError,forms,python-3.x,cgi,Forms,Python 3.x,Cgi,我想从Udacity的全堆栈基础课程中做一个练习。我在BaseHTTPRequestHandler中的子类中有do\u POST方法,基本上我希望获得一个名为message的POST值,并以多部分表单提交,这是该方法的代码: def do_POST(self): try: if self.path.endswith("/Hello"): self.send_response(200) self.send_header('Co

我想从Udacity的全堆栈基础课程中做一个练习。我在
BaseHTTPRequestHandler
中的子类中有
do\u POST
方法,基本上我希望获得一个名为
message
的POST值,并以多部分表单提交,这是该方法的代码:

def do_POST(self):
    try:
        if self.path.endswith("/Hello"):
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers
            ctype, pdict = cgi.parse_header(self.headers['content-type'])
            if ctype == 'multipart/form-data':
                fields = cgi.parse_multipart(self.rfile, pdict)
                messagecontent = fields.get('message')
            output = ""
            output += "<html><body>"
            output += "<h2>Ok, how about this?</h2>"
            output += "<h1>{}</h1>".format(messagecontent)
            output += "<form method='POST' enctype='multipart/form-data' action='/Hello'>"
            output += "<h2>What would you like to say?</h2>"
            output += "<input name='message' type='text'/><br/><input type='submit' value='Submit'/>"
            output += "</form></body></html>"
            self.wfile.write(output.encode('utf-8'))
            print(output)
            return
    except:
        self.send_error(404, "{}".format(sys.exc_info()[0]))
        print(sys.exc_info()    )
def do_POST(self):
尝试:
如果self.path.endswith(“/Hello”):
自我发送_响应(200)
self.send_标题('Content-type','text/html')
self.end\u头文件
ctype,pdict=cgi.parse_头(self.headers['content-type'])
如果ctype==“多部分/表单数据”:
fields=cgi.parse_multipart(self.rfile,pdict)
messagecontent=fields.get('message')
output=“”
输出+=“”
输出+=“好的,这个怎么样?”
输出+=“{}”。格式(messagecontent)
输出+=“”
输出+=“您想说什么?”
输出+=“
” 输出+=“” self.wfile.write(output.encode('utf-8')) 打印(输出) 返回 除: self.send_错误(404,“{}”.format(sys.exc_info()[0])) 打印(sys.exc_info())

问题是,
cgi.parse\u multipart(self.rfile,pdict)
抛出了一个异常:
TypeError:cannotconcat bytes to str
,实现在课程的视频中提供,但他们使用的是Python 2.7,我使用的是Python 3,我整个下午都在寻找解决方案,但找不到任何有用的东西,在Python3中,读取从多部分表单传递的数据的正确方法是什么

我来到这里是为了解决和你一样的问题。 我找到了一个愚蠢的解决办法。 我只是使用编码选项将字典中的“边界”项从字符串转换为字节

    ctype, pdict = cgi.parse_header(self.headers['content-type'])
    pdict['boundary'] = bytes(pdict['boundary'], "utf-8")
    if ctype == 'multipart/form-data':
            fields = cgi.parse_multipart(self.rfile, pdict)

就我而言,它似乎工作正常。

另一个黑客解决方案是编辑
cgi
模块的源代码

parse_multipart
的最开始处(第226行附近): 将
边界的用法更改为
str(边界)


我在做同样的课程,遇到同样的问题。我现在使用的不是cgi,而是解析库。就在几节课之前,在同一课程中也展示了这一点

from urllib.parse import parse_qs

length = int(self.headers.get('Content-length', 0))
body = self.rfile.read(length).decode()
params = parse_qs(body)

messagecontent = params["message"][0]

您必须去掉表单中的
enctype='multipart/form data'

在我的例子中,我使用
cgi.FieldStorage
来提取文件和名称,而不是
cgi.parse\u multipart

form = cgi.FieldStorage(
    fp=self.rfile,
    headers=self.headers,
    environ={'REQUEST_METHOD':'POST',
             'CONTENT_TYPE':self.headers['Content-Type'],
             })

print('File', form['file'].file.read())
print('Name', form['name'].value)

要将导师的代码更改为适用于Python 3,您必须处理以下三条错误消息:

如果您收到这些错误消息

c_type, p_dict = cgi.parse_header(self.headers.getheader('Content-Type'))
AttributeError: 'HTTPMessage' object has no attribute 'getheader'


跑步时

c_type, p_dict = cgi.parse_header(self.headers.getheader('Content-Type'))
if c_type == 'multipart/form-data':
                fields = cgi.parse_multipart(self.rfile, p_dict)
                message_content = fields.get('message')
这适用于你

解决方案

首先,更改第一行以适应Python 3:

- c_type, p_dict = cgi.parse_header(self.headers.getheader('Content-Type'))
+  c_type, p_dict = cgi.parse_header(self.headers.get('Content-Type'))
其次,为了修复“str”对象没有任何属性“decode”的错误,这是因为从Python 3开始,字符串被转换为unicode字符串,而不是像Python 3那样等价于字节字符串,所以在上面的一行下面添加这一行:

p_dict['boundary'] = bytes(p_dict['boundary'], "utf-8")
第三,要纠正pdict中没有“内容长度”的错误,只需在if语句之前添加以下行:

content_len = int(self.headers.get('Content-length'))
p_dict['CONTENT-LENGTH'] = content_len
my Github上的完整解决方案:


这给了我另一个错误,
'bytes'对象没有属性'readline'
。如何处理此问题?@AmitBadhekaPykihStaff您可以尝试从io导入字节io执行以下
,然后执行
cgi.parse_multipart(字节io(您的内容),pdict)
- c_type, p_dict = cgi.parse_header(self.headers.getheader('Content-Type'))
+  c_type, p_dict = cgi.parse_header(self.headers.get('Content-Type'))
p_dict['boundary'] = bytes(p_dict['boundary'], "utf-8")
content_len = int(self.headers.get('Content-length'))
p_dict['CONTENT-LENGTH'] = content_len