我有问题,HTTP头,他们在ASCII编码,我想提供一个视图下载文件名称可以是非ASCII。
response['Content-Disposition'] = 'attachment; filename="%s"' % (vo.filename.encode("ASCII","replace"), )
我不想用非ASCII文件名服务于同样的问题静态文件,但在这种情况下,将与文件系统的一个问题,它的文件名编码。 (我不知道目标OS)。
我已经尝试过urllib.quote(),但它会引发KeyError异常例外。
也许我做错了什么,但也许这是不可能的。
Answer 1:
这是一个常见问题。
有没有互操作的方式来做到这一点。 有些浏览器实现专有扩展(IE,Chrome浏览器),其他实现RFC 2231(火狐,歌剧)。
见测试用例在http://greenbytes.de/tech/tc2231/ 。
更新:如2012年11月的,目前所有的桌面浏览器支持在RFC 6266和RFC 5987中定义的编码(野生> = 6,IE> = 9,铬,Firefox,歌剧,Konqueror中)。
Answer 2:
不要在内容处理发送的文件名。 有没有办法让非ASCII头参数工作跨浏览器(*)。
相反,仅发送“内容处置:附件”,并留下文件名作为网址的结尾(PATH_INFO)部分的URL编码的UTF-8字符串,浏览器回暖,默认情况下使用。 UTF-8网址是更加可靠的浏览器比任何与内容处置处理。
(*:其实,甚至有不是一个现行的标准,说应该如何作为的RFC 2616,2231和2047是非常不正常的关系,一些朱利安试图在规范层面得到清理完成一致的浏览器支持。在遥远的未来。)
Answer 3:
需要注意的是,2011年, RFC 6266 (特别是附录d)在权衡对这个问题,并有具体的建议遵循。
也就是说,你可以发出一个filename
,只有ASCII字符,然后filename*
与那些理解代理RFC 5987格式的文件名。
通常,这会看起来像filename="my-resume.pdf"; filename*=UTF-8''My%20R%C3%A9sum%C3%A9.pdf
filename="my-resume.pdf"; filename*=UTF-8''My%20R%C3%A9sum%C3%A9.pdf
,其中的Unicode文件名( “我的Résumé.pdf”)被编码成UTF-8,然后百分比编码(注意,不使用+
为空格)。
请不要实际阅读RFC 6266和RFC 5987(或使用抽象这个给你一个强大的和测试库),这里是缺乏重要的细节,我的总结。
Answer 4:
我可以说,我已经使用了较新的(成功RFC 5987 )指定用电子邮件的形式(编码的头格式RFC 2231 )。 我想出了这是基于从Django的sendfile的项目下列代码解决方案。
import unicodedata
from django.utils.http import urlquote
def rfc5987_content_disposition(file_name):
ascii_name = unicodedata.normalize('NFKD', file_name).encode('ascii','ignore').decode()
header = 'attachment; filename="{}"'.format(ascii_name)
if ascii_name != file_name:
quoted_name = urlquote(file_name)
header += '; filename*=UTF-8\'\'{}'.format(quoted_name)
return header
# e.g.
# request['Content-Disposition'] = rfc5987_content_disposition(file_name)
我只测试我的代码上的Python 3.4和Django 1.8。 因此,类似的Django的sendfile的解决方案可以更好地适合你。
有一个长期的票在Django的追踪器承认这一点,但没有补丁尚未AFAICT建议。 所以,不幸的是这是接近使用一个强大的测试库,我能找到,请让我知道,如果有更好的解决方案。
Answer 5:
截至2018年,一个解决方案是目前在Django 2.1(含情脉脉七年作为一个后可用公开售票 )。 您可以使用as_attachment
内置参数FileResponse 。 例如,为了返回一个文件output_file
MIME类型output_mime_type
作为HTTP响应:
response = FileResponse(open(output_file, 'rb'), as_attachment=True, content_type=output_mime_type)
return response
或者,如果你不能使用FileResponse
,你可以使用相关的部分从源头上改变Content-Disposition
更直接。 下面是该源目前是这样的:
from urllib.parse import quote
try:
document.file_name.encode('ascii')
file_expr = 'filename="{}"'.format(filename)
except UnicodeEncodeError:
# Handle a non-ASCII filename
file_expr = "filename*=utf-8''{}".format(quote(filename))
response['Content-Disposition'] = 'attachment; {}'.format(file_expr)
Answer 6:
黑客:
if (Request.UserAgent.Contains("IE"))
{
// IE will accept URL encoding, but spaces don't need to be, and since they're so common..
filename = filename.Replace("%", "%25").Replace(";", "%3B").Replace("#", "%23").Replace("&", "%26");
}
文章来源: How to encode UTF8 filename for HTTP headers? (Python, Django)