pallets / flask

The Python micro framework for building web applications.
https://flask.palletsprojects.com
BSD 3-Clause "New" or "Revised" License
67.64k stars 16.16k forks source link

request.files is empty after POSTing a file #1384

Closed bepetersn closed 9 years ago

bepetersn commented 9 years ago

Hey guys, I don't know if this is the right place to make this bug report, but I could sure use some help, I have been banging my head against a wall for a bit. See this repo where I'm reproducing my error: https://github.com/bepetersn/special-repo.

I'm seeing weird behavior around the Flask request object. After uploading a file with the requests library, e.g. requests.post(uri, files=<my_files>), by the time the request propagated to my view function, request.files was empty. Oddly, I observed that the contents of the file itself was available under request.form[None].

My only lead was that when I debugged this at length, I saw that the request data was being treated as a mimetype of "application/x-www-form-urlencoded" rather than the correct "multipart/form" for uploading binary files... But, I just threw this example together really quickly, and I'm not seeing that right now, so I'm no longer sure.

I've also seen some other errors on this repo involving calling request.data vs request.form. I don't really know anything about that. I'd greatly appreciate a pointer in the right direction.

SBillion commented 9 years ago

No problem with Flask but with your way to use requests:

http://docs.python-requests.org/en/latest/user/advanced/#streaming-uploads

You should send your attachments as a stream. It doesn't like you are sending any binary data in your current requests.post

Le mercredi 18 mars 2015 à 07:55 -0700, Brian Everett Peterson a écrit :

Hey guys, I don't know if this is the right place to make this bug report, but I could sure use some help, I have been banging my head against a wall for a bit. See this repo where I'm reproducing my error: https://github.com/bepetersn/special-repo.

I'm seeing weird behavior around the Flask request object. After uploading a file with the requests library, e.g. requests.post(uri, files=), by the time the request propagated to my view function, request.files was empty. Oddly, I observed that the contents of the file itself was available under request.form[None].

My only lead was that when I debugged this at length, I saw that the request data was being treated as a mimetype of "application/x-www-form-urlencoded" rather than the correct "multipart/form" for uploading binary files... But, I just threw this example together really quickly, and I'm not seeing that right now, so I'm no longer sure.

I've also seen some other errors on this repo involving calling request.data vs request.form. I don't really know anything about that. I'd greatly appreciate a pointer in the right direction.

— Reply to this email directly or view it on GitHub.

bepetersn commented 9 years ago

Hmmm, merci beaucoup pour votre réponse rapide. :) I thought maybe it had to do more with requests, I just couldn't prove my reasoning. Do you think the size of the file leaves a chance for it throw the POST request off? I have seen this error around ~4 times, but similar operations to this have been done thousands of times in production. I'm wondering if that fits with your understanding of why this is happening.

bepetersn commented 9 years ago

I'm gonna throw this over to the requests github as well. In the meantime, I updated my repo: https://github.com/bepetersn/special-repo. Would you be willing to look at that and tell me if that's a valid way to stream the bytes with requests, like you were suggesting? It still did not work for me.

bepetersn commented 9 years ago

See my new issue, with slightly more information at their repo: https://github.com/kennethreitz/requests/issues/2505. It looks to me like requests is SLIGHTLY incorrectly encoding the file metadata (specifically the document filename) for the form/multipart mimetype. Werkzeug gives up in interpreting it, doesn't create a werkzeug.datastructures.FileStorage instance, and thus doesn't populate request.files.

bepetersn commented 9 years ago

So others know, this behavior can be reproduced if there is a newline character in the title of a file POSTed with requests. Under the hood, it results in requests encoding the document differently (see RFC 2231), and werkzeug doesn't handle this possibility.