如何编码HTTP头的UTF8文件名? (Python,Django)
我有HTTP标题的问题,他们用ASCII编码,我想提供一个下载名称可以是非ASCII的文件的视图。
response['Content-Disposition'] = 'attachment; filename="%s"' % (vo.filename.encode("ASCII","replace"), )
我不想使用静态文件来处理与非ASCII文件名相同的问题,但在这种情况下,文件系统会出现问题,并且是文件名编码。 (我不知道目标操作系统。)
我已经尝试urllib.quote(),但它引发了KeyErrorexception。
可能我做错了,但也许是不可能的。
这是一个常见问题。
没有可互操作的方式来做到这一点。 一些浏览器实现专有扩展(IE,Chrome),其他实现RFC 2231(Firefox,Opera)。
请参阅http://greenbytes.de/tech/tc2231/上的testing案例。;
更新:截至2012年11月,所有当前的桌面浏览器都支持RFC 6266和RFC 5987(Safari> = 6,IE> = 9,Chrome,Firefox,Opera,Konqueror)中定义的编码。
不要在Content-Disposition中发送文件名。 跨浏览器(*)无法使非ASCII标头参数工作。
相反,只发送“内容处置:附件”,并将文件名保留为URL编码的UTF-8string,并放在URL的尾部(PATH_INFO)中,供浏览器默认使用。 浏览器可以更加可靠地处理UTF-8 URL,而不是使用Content-Disposition进行处理。
(*:实际上,甚至连当前的标准都没有说明它应该如何完成,因为RFC 2616,2231和2047之间的关系非常不正常,Julian正试图在规范级别上清除它。在遥远的将来。)
请注意,在2011年, RFC 6266 (尤其是附录D)对此问题进行了考虑,并提出了具体的build议。
也就是说,您只能使用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文件名(“MyRésumé.pdf”)被编码成UTF-8,然后被编码为百分号(注意,不要使用+
作为空格)。
请确实阅读RFC 6266和RFC 5987(或者使用一个强大且经过testing的库,为您抽象出这个库),因为我的总结缺乏重要的细节。
黑客:
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"); }
我可以说,我已经成功地使用了指定使用电子邮件表单( RFC 2231 )编码的头文件的更新( RFC 5987 )格式。 我想出了以下基于django-sendfile项目代码的解决scheme。
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 # eg # request['Content-Disposition'] = rfc5987_content_disposition(file_name)
我只用Django 1.8在Python 3.4上testing了我的代码。 所以django-sendfile中的类似解决scheme可能更适合你。
Django的追踪器中有一个长期的票据承认这一点,但尚未提出补丁。 所以不幸的是,这与使用强大的经过testing的库是如此接近,请让我知道是否有更好的解决scheme。