cgi.parse_multipart function throws TypeError in Python 3

匿名 (未验证) 提交于 2019-12-03 08:46:08

问题:

I'm trying to make an exercise from Udacity's Full Stack Foundations course. I have the do_POST method inside my subclass from BaseHTTPRequestHandler, basically I want to get a post value named message submitted with a multipart form, this is the code for the method:

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()    ) 

The problem is that the cgi.parse_multipart(self.rfile, pdict) is throwing an exception: TypeError: can't concat bytes to str, the implementation was provided in the videos for the course, but they're using Python 2.7 and I'm using python 3, I've looked for a solution all afternoon but I could not find anything useful, what would be the correct way to read data passed from a multipart form in python 3?

回答1:

I've came across here to solve the same problem like you have. I found a silly solution for that. I just convert 'boundary' item in the dictionary from string to bytes with an encoding option.

    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) 

In my case, It seems work properly.



回答2:

Another hack solution is to edit the source of the cgi module.

At the very beginning of the parse_multipart (around the 226th line): Change the usage of the boundary to str(boundary)

... boundary = b"" if 'boundary' in pdict:     boundary = pdict['boundary'] if not valid_boundary(boundary):     raise ValueError('Invalid boundary in multipart form: %r'                         % (boundary,))  nextpart = b"--" + str(boundary) lastpart = b"--" + str(boundary) + b"--"  ... 


回答3:

I am doing the same course and was running into the same problem. Instead of getting it to work with cgi I am now using the parse library. This was shown in the same course just a few lessons earlier.

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] 

And you have to get rid of the enctype='multipart/form-data' in your form.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!