Chr*_*ski 45 python django escaping http http-headers
我有HTTP标头的问题,它们用ASCII编码,我想提供一个视图,用于下载名称可以是非ASCII的文件.
response['Content-Disposition'] = 'attachment; filename="%s"' % (vo.filename.encode("ASCII","replace"), )
Run Code Online (Sandbox Code Playgroud)
我不想使用静态文件为非ASCII文件名提供同样的问题,但在这种情况下,文件系统及其文件名编码会出现问题.(我不知道目标操作系统.)
我已经尝试过urllib.quote(),但它引发了KeyError异常.
可能我做错了但也许这是不可能的.
Jul*_*hke 36
这是一个FAQ.
没有可互操作的方法来做到这一点.一些浏览器实现专有扩展(IE,Chrome),其他实现RFC 2231(Firefox,Opera).
请参阅http://greenbytes.de/tech/tc2231/上的测试用例.
更新:截至2012年11月,所有当前桌面浏览器都支持RFC 6266和RFC 5987中定义的编码(Safari> = 6,IE> = 9,Chrome,Firefox,Opera,Konqueror).
bob*_*nce 31
不要在Content-Disposition中发送文件名.无法使非ASCII标头参数跨浏览器(*)工作.
相反,只发送"Content-Disposition:attachment",并将文件名作为URL编码的UTF-8字符串保留在URL的尾随(PATH_INFO)部分,以便浏览器默认选择和使用.浏览器可以更可靠地处理UTF-8 URL,而不是使用Content-Disposition.
(*:实际上,由于RFC 2616,2231和2047之间的关系非常不正常,因此甚至没有一个当前的标准说明应该如何完成,这是Julian试图在规范级别上清除的东西.一致的浏览器支持是在遥远的未来.)
Ala*_* H. 29
请注意,在2011年,RFC 6266(特别是附录D)对此问题进行了权衡,并提出了具体的建议.
也就是说,您可以filename只发出一个ASCII字符,然后filename*使用RFC 5987格式的文件名发送给那些了解它的代理.
通常情况下filename="my-resume.pdf"; filename*=UTF-8''My%20R%C3%A9sum%C3%A9.pdf,Unicode文件名("MyRésumé.pdf")编码为UTF-8然后进行百分比编码(注意,不要+用于空格).
请实际阅读RFC 6266和RFC 5987(或使用一个强大且经过测试的库,为您提取此内容),因为我的摘要缺乏重要细节.
我可以说我已经成功地使用了较新的 ( 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)
Run Code Online (Sandbox Code Playgroud)
我只用Django 1.8在Python 3.4上测试了我的代码。因此django-sendfile 中的类似解决方案可能更适合您。
Django 的跟踪器中有一张长期存在的票证,它承认这一点,但尚未提出任何补丁。所以不幸的是,这与我能找到的使用强大的测试库一样接近,如果有更好的解决方案,请告诉我。
截至2018年,Django 2.1现在已经有一个解决方案(作为公开票证失去了七年的历史)。您可以使用FileResponse中as_attachment内置的参数。例如,要返回MIME类型的文件作为HTTP响应:output_fileoutput_mime_type
response = FileResponse(open(output_file, 'rb'), as_attachment=True, content_type=output_mime_type)
return response
Run Code Online (Sandbox Code Playgroud)
或者,如果您不能使用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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
28161 次 |
| 最近记录: |