Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python-requests post with unicode filenames

I've read through several related questions here on SO but didn't manage to find a working solution.

I have a Flask server with this simplified code:

app = Flask(__name__)
api = Api(app)


class SendMailAPI(Resource):
    def post(self):
        print request.files
        return Response(status=200)

api.add_resource(SendMailAPI, '/')

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

Then in the client:

# coding:utf-8

import requests

eng_file_name = 'a.txt'
heb_file_name = u'א.txt'

requests.post('http://localhost:5000/', files={'file0': open(eng_file_name, 'rb')})
requests.post('http://localhost:5000/', files={'file0': open(heb_file_name, 'rb')})

When sending the first request with the non-utf-8 filename the server receives the request with the file and prints ImmutableMultiDict([('file0', <FileStorage: u'a.txt' (None)>)]), but when sending the file with the utf-8 filename the server doesn't seem to receive the file as it prints ImmutableMultiDict([]).

I'm using requests 2.3.0 but the problem doesn't resolve with the latest version as well (2.8.1), Flask version is 0.10.1 and Flask-RESTful version is 0.3.4.

I've done some digging in requests code and the request seems to be sent ok (ie with the file), and I printed the request right before it is being sent and see the file name was indeed encoded to RFC2231:

--6ea257530b254861b71626f10a801726
Content-Disposition: form-data; name="file0"; filename*=utf-8''%D7%90.txt

To sum things up, I'm not entirely sure if the problem lies within requests that doesn't properly attach the file to the request or if Flask is having issues with picking up files with file names that are encoded according to RFC2231.

UPDATE: Came across this issue in requests GitHub: https://github.com/kennethreitz/requests/issues/2505

like image 749
DeepSpace Avatar asked Nov 15 '15 08:11

DeepSpace


1 Answers

I think maybe there's confusion here on encoding here -

eng_file_name = 'a.txt'  # ASCII encoded, by default in Python 2
heb_file_name = u'א.txt'  # NOT UTF-8 Encoded - just a unicode object

To send the second one to the server what you want to do is this:

requests.post('http://localhost:5000/', files={'file0': open(heb_file_name.encode('utf-8'), 'rb')})

I'm a little surprised that it doesn't throw an error on the client trying to open the file though - you see nothing on the client end indicating an error?

EDIT: An easy way to confirm or deny my idea is of course to print out the contents from inside the client to ensure it's being read properly.

like image 99
jimjkelly Avatar answered Sep 20 '22 06:09

jimjkelly