用werkzeug处理unicode文本?

所以我试图让浏览器下载一个具有特定名称的文件,该文件存储在数据库中。 为了防止文件名冲突,文件使用GUID保存在磁盘上,当需要实际下载文件时,数据库的文件名将提供给浏览器。 这个名字是用日语写的,当我在页面上显示它时,它很好,所以它在数据库中保存OK。 当我尝试实际上让浏览器以该名称下载它时:

return send_from_directory(app.config['FILE_FOLDER'], name_on_disk, 
                           as_attachment=True, attachment_filename = filename)

Flask引发错误:

UnicodeEncodeError: 'ascii' codec can't encode characters in position 15-20: 
ordinal not in range(128)

这个错误似乎不是来自我的代码,而是来自Werkzeug的一部分:

/werkzeug/http.py", line 150, in quote_header_value
value = str(value)

这是为什么发生? 根据他们的文档,Flask是“100%Unicode”

在我重写我的代码之前,我确实遇到了这个问题,并通过在Werkzeug中修改了很多东西来修复它,但我真的不希望为已部署的应用程序执行此操作,因为这是一种痛苦和不好的做法。

Python 2.7.6 (default, Nov 26 2013, 12:52:49) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.

文件名=“[얼티메이트] [131225]电视アニメ「キルクリル」オリジナルサウンドラック(FLAC).zip”

打印repr(文件名)

'[xecx96xbcxedx8bxb0xebxa9x94xecx9dxb4xedx8axb8] [131225] TVxe3x82xa2xe3x83x8bxe3x83xa1xe3x80x8cxe3x82xadxe3x83xabxe3x83xa9xe3x82xadxe3x83xabxe3x80x8dxe3x82xaaxe3x83xaaxe3x82xb8xe3x83x8axe3x83xabxe3x82xb5xe3x82xa6xe3x83xb3xe3x83x89xe3x83x88xe3x83xa9xe3x83x83xe3x82xaf (FLAC).zip'
>>> 

在处理非ASCII数据时,应该明确地传递unicode字符串(输入unicode )。 通常在Flask中,bytestrings被假定为具有ascii编码。


我有类似的问题。 我原本以此为附件发送文件:

return send_file(dl_fd,
                 mimetype='application/pdf',
                 as_attachment=True,
                 attachment_filename=filename)

其中dl_fd是我的文件的文件描述符。

unicode文件名不起作用,因为HTTP标头不支持它。 相反,基于来自这个Flask问题的信息和RFC 2231的这些测试用例,我重写了上面的内容来编码文件名:

response = make_response(send_file(dl_fd,
                                   mimetype='application/pdf'
                                   ))
response.headers["Content-Disposition"] = 
    "attachment; " 
    "filename*=UTF-8''{quoted_filename}".format(
        quoted_filename=urllib.quote(filename.encode('utf8'))
    )

return response

基于测试用例,上述内容不适用于IE8,但适用于列出的其他浏览器。 (我亲自在Mac上测试了Firefox,Safari和Chrome)


你应该使用像这样的东西:

@route('/attachment/<int:attachment_id>/<filename>', methods=['GET'])
def attachment(attachment_id, filename):
    attachment_meta = AttachmentMeta(attachment_id, filename)
    if not attachment_meta:
        flask.abort(404)
    return flask.send_from_directory(
        directory=flask.current_app.config['UPLOAD_FOLDER'],
        filename=attachment_meta.filepath,
    )

这样url_for('attachment',1,u'Москва 北京 תֵּל־אָבִיב.pdf')将产生:

/attachment/1/%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0%20%E5%8C%97%E4%BA%AC%20%D7%AA%D6%B5%D6%BC%D7%9C%D6%BE%D7%90%D6%B8%D7%91%D6%B4%D7%99%D7%91.pdf

浏览器将以正确的unicode名称显示或保存此文件。 不要使用as_attachment=True ,因为这不起作用。

链接地址: http://www.djcxy.com/p/77481.html

上一篇: handling unicode text with werkzeug?

下一篇: Can you have more than one Google Site Verification tags