cgi.parse_multipart函数在Python 3中抛出TypeError

cva*_*ina 8 forms cgi python-3.x

我正在尝试从Udacity的Full Stack Foundations课程中进行练习.我do_POST在我的子类中有方法BaseHTTPRequestHandler,基本上我想获得一个名为messagesubmit with multipart form 的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()    )
Run Code Online (Sandbox Code Playgroud)

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

小智 16

我在这里遇到了像你一样解决同样的问题.我找到了一个愚蠢的解决方案.我只是将字典中的'boundary'项从字符串转换为带有编码选项的字节.

    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)
Run Code Online (Sandbox Code Playgroud)

在我的情况下,似乎工作正常.

  • 这给了我另一个错误,“bytes”对象没有属性“readline”。如何处理? (2认同)

小智 5

要更改教师的代码以使其适用于Python 3,您必须消除以下三种错误消息:

如果收到这些错误消息

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

要么

 boundary = pdict['boundary'].decode('ascii')
AttributeError: 'str' object has no attribute 'decode'
Run Code Online (Sandbox Code Playgroud)

要么

headers['Content-Length'] = pdict['CONTENT-LENGTH']
KeyError: 'CONTENT-LENGTH'
Run Code Online (Sandbox Code Playgroud)

跑步时

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')
Run Code Online (Sandbox Code Playgroud)

这适用于您。

首先,更改第一行以适应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'))
Run Code Online (Sandbox Code Playgroud)

其次,要修复“ str”对象不具有任何属性“ decode”的错误,这是因为从Python 3开始,字符串的变化被转换为unicode字符串,而不是在Python 3中等效于字节字符串,因此添加这条线在上面的下面:

p_dict['boundary'] = bytes(p_dict['boundary'], "utf-8")
Run Code Online (Sandbox Code Playgroud)

第三,要解决在pdict中没有'CONTENT-LENGTH'的错误,只需在if语句之前添加以下行:

content_len = int(self.headers.get('Content-length'))
p_dict['CONTENT-LENGTH'] = content_len
Run Code Online (Sandbox Code Playgroud)

我的Github上的完整解决方案:

https://github.com/rSkogeby/web-server