我遇到了一个相当奇怪的情况,我很难在现有的 Django 应用程序中进行跟踪。其中一个从 APIView 继承的视图在用户进行 POST 调用时返回一个文件。端点工作正常,但是当下载的文件到达客户端机器时会发生一些奇怪的事情。当浏览器接收到文件时,文件扩展名已被重命名为尾随下划线。(因此假设文件最初是“test.txt”,客户端收到的版本将是“test.txt_”)。
据我所知,就在 APIView 中返回响应对象之前,content-type 和 content-disposition 标头看起来是正确的。例如:
Content-Type: application/octet-stream
Content-Disposition: attachment;filename="test.txt"
Run Code Online (Sandbox Code Playgroud)
同一个文件,当它出现在 Chrome 下载中时,被命名为“test.txt_” - 尾随下划线。我在 Firefox 中尝试过同样的事情,它似乎可以正确下载。不幸的是,告诉我们的大多数用户切换浏览器是行不通的。
我试过了:
corsheaders.middleware.CorsMiddleware
django.contrib.sessions.middleware.SessionMiddleware
django.middleware.locale.LocaleMiddleware
django.middleware.common.CommonMiddleware
django.middleware.csrf.CsrfViewMiddleware
django.contrib.auth.middleware.AuthenticationMiddleware
django.contrib.messages.middleware.MessageMiddleware
Run Code Online (Sandbox Code Playgroud)
到目前为止,其他人遇到的任何类似问题似乎都略有不同(即:Internet Explorer 删除了扩展中的句点并将其替换为下划线)。
对这里可能发生的事情有任何猜测吗?我有点难住了。
下载文件时,Chrome 如何确定保存到磁盘的文件名?
每当我从我正在处理的特定网站(作为开发人员)下载文件时,Chrome 都会在文件扩展名的末尾附加一个下划线。(请参阅:Windows 上的 Chrome 在下载的文件中添加尾随下划线?)。我一直在尝试各种内容类型和内容处置标头,Chrome 似乎忽略了 Content-Disposition 标头中指定的文件名。例如,如果我发出下载文件的请求,并且返回的响应包含以下标头(以及其他标头):
Content-Disposition: attachment;filename="example.pdf"
Content-Type: application/pdf
Run Code Online (Sandbox Code Playgroud)
...保存到磁盘的文件名仍然是原始文件名。在此示例中,原始文件名为test.pdf,并且不是将其另存为example.pdf(如 Content-Disposition 中指定的),而是以test.pdf. 这似乎适用于任何类型的文件类型 - 即使是像 .txt 文件这样简单的文件类型。似乎没有任何其他 HTTP 响应标头指定文件名。
Chrome 是否做了一些特殊的事情来确定保存到磁盘的文件的名称?如果是这样,是否可以覆盖此行为?
据我所知,Chrome 会重命名某些它认为存在安全风险的下载文件(例如:将 .lnk 重命名为 .download),但即使在这种情况下,它仍然会忽略我的 Content-Disposition 标头以获取安全文件类型。