在 IE11 中从 Cloudfront 下载的可执行文件 (Windows 7) 不带文件扩展名的下载

Executable downloaded from Cloudfront in IE11 (Windows 7) downloads without a file extension

它的 long-short 是 .exe 从 Cloudfront 下载的 IE11/Win7 次下载(使用签名 URL),没有扩展名 (exe_file.exe -> exe_file)

认为这与描述的问题相同here(在许多其他地方)因为文件没有重命名exe_file_exe,刚刚删除了扩展名。

文件由 S3 的 Cloudfront 提供 - 并通过 aws-cli

上传
$ aws s3 cp exe_file.exe s3://cdn/exe_file.exe --content-type "application/x-msdownload"

据我所知,content-type 参数并非绝对必要,因为 CF/S3/something 在某些时候会尝试进行一些智能 MIME 分配(另外,之前,当我在没有该参数的情况下上传,检查下载 headers 将显示正确的 MIME 类型)。

Headers 下载文件时收到

HTTP/1.1 200 OK
Content-Type: application/x-msdownload
Content-Length: 69538768
Connection: keep-alive
Date: Tue, 27 Dec 2016 17:36:51 GMT
Last-Modified: Thu, 22 Dec 2016 22:31:59 GMT
ETag: "c8fc68a920e198dca95e5549f8657bfb"
Accept-Ranges: bytes
Server: AmazonS3
Age: 335
X-Cache: Hit from cloudfront

这个 发生在 Windows 7 上的 IE11 - 它在 IE11/Windows 10 上工作正常(我只说但我没有试过,因为例如,IE8——你付不起足够的钱让我自己通过它)。其他下载不会发生这种情况 - dmg_file.dmglinux_file.zip 都与扩展一起下载。其他浏览器也不受影响——它们都在 S3.

中下载文件 as-is

我已经尝试过使用和不使用 AV - 这没有区别。

您需要正确设置content-disposition

使用 HTTP header 强制 SaveAs 为了强制浏览器在单击超链接时显示 SaveAs 对话框,您必须在要下载的文件的 HTTP 响应中包含以下 header:

Content-Disposition: attachment; filename="<file name.ext>"; filename*=utf-8''<file name.ext>

注意:那些不支持 RFC 5987 编码的用户代理会忽略出现在 filename.

之后的 filename*

您希望在“另存为”对话框中显示的文件名在哪里(如 finances.xls 或 mortgage.pdf)- 不带 <> 符号。

您必须牢记以下几点:

  1. 文件名应采用 US-ASCII 字符集且不应包含特殊字符:< > \ " / : | ? * space.
  2. 文件名不应指定任何目录路径信息。
  3. 文件名应包含在双引号中,但大多数浏览器将支持不带双引号的文件名。

古代浏览器还需要以下内容(现在不需要,但对于万无一失的解决方案可能值得这样做):

  1. Content-Type header 应该在 Content-Disposition.
  2. 之前
  3. Content-Type header 应该引用未知的 MIME 类型(至少在旧浏览器消失之前)。

所以,您应该使用 cp 和选项:

  1. --content-type (string) 为此操作指定明确的内容类型。此值覆盖任何猜测的 MIME 类型。
  2. --content-disposition (string) 指定 object.
  3. 的展示信息
  4. --metadata-directive REPLACE 指定元数据是从源 object 复制还是替换为复制 S3 objects 时提供的元数据。

请注意,如果您使用以下任何参数:--content-typecontent-language--content-encoding--content-disposition--cache-control--expires,如果您希望复制的 object 具有指定的元数据值,则需要为 non-multipart 个副本指定 --metadata-directive REPLACE

尝试:

aws s3 cp exe_file.exe s3://cdn/exe_file.exe --content-type "application/x-msdownload" --content-disposition "attachment; filename=\"exe_file.exe\"; filename*=utf-8''exe_file.exe" --metadata-directive REPLACE

除了已接受的答案外,我还向 Cloudfront Signer 提供了自己的 response-content-disposition 参数:

在 Python 中,看起来像

from botocore.signers import CloudFrontSigner

def generate_presigned_url(filename, headers={}):
    cf_signer = CloudFrontSigner(CF_KEY_ID, rsa_signer)
    headers = '&'.join(["%s=%s" % (key, urllib.quote_plus(value)) for key, value in headers.iteritems()])

    return cf_signer.generate_presigned_url(
        'https://' + CF_DOMAIN + '/' + filename + ("" if len(headers) == 0 else "?%s" % (headers)),
        # ... other params
    )

使用

调用
cloudfront.generate_presigned_url(file_name, {
    'response-content-disposition': 'attachment; filename="exe_file.exe"; filename*=utf-8\'\'exe_file.exe'
})