thkang
thkang

Reputation: 11543

flask send_file and unicode filename : broken in IE

I wrote a function that generates some csv file on the fly and sends to user for download.

the code is below:

@app.route('/survey/<survey_id>/report')
def survey_downloadreport(survey_id):  
    survey, bsonobj = survey_get(survey_id)
    resps = response_get_multi(survey_id)

    fields = ["_id", "sid", "date", "user_ip"]
    fields.extend(survey.formfields)    

    csvf = StringIO.StringIO()
    wr = csv.DictWriter(csvf, fields, encoding = 'cp949')
    wr.writerow(dict(zip(fields, fields)))
    for resp in resps :
        wr.writerow(resp)

    csvf.seek(0)

    now = datetime.datetime.now()
    report_name = survey.name + "(" + \
                  now.strftime("%Y-%m-%d-%H:%M:%S") +\
                  ")" + ".csv"

    report_name = report_name.encode("utf-8")



    return send_file(csvf,
                 as_attachment = True,
                 attachment_filename = report_name)

as you can see, the filename is converted from unicode to string and in utf-8 (to be precise, they are in Korean letters.)

the problem is, filenames are completely broken in when page is viewed in IE(no problem in chrome).

It seems like the header has to be edited to match parsing rules for different browsers, but I have no idea how I can do this in flask.

Upvotes: 2

Views: 3142

Answers (2)

bobince
bobince

Reputation: 536359

Using Content-Disposition: attachment; filename="..." to set the name of a downloaded file - which is what Flask's send_file does - is not reliable for non-ASCII characters.

Until there is support for RFC 5987 in the werkzeug.http library that Flask uses, and in all the browsers you want to target, this is not fixable.

In the meantime, a more reliable cross-browser method is to put the UTF-8-URL-encoded filename in the trailing part of the URI when you make links to it, ie:

IRI path: /survey/1/report/안녕.csv
URI path: /survey/1/report/%ec%95%88%eb%85%95.csv

See How to encode UTF8 filename for HTTP headers? (Python, Django) for background.

Upvotes: 2

Martin v. L&#246;wis
Martin v. L&#246;wis

Reputation: 127447

Try adding

mimetype = 'text/csv; charset=x-EBCDIC-KoreanAndKoreanExtended'

to send_file.

Upvotes: 3

Related Questions