其中的很长一段时间是在IE11 / Win7下载中从Cloudfront(使用签名的URL)下载的.exe
,没有扩展名( exe_file.exe -> exe_file
)
我不认为这是同样的问题(在许多其他地方),因为该文件没有被重命名为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 /东西,在某种程度上,试图做一些智能MIME分配(加,之前,当我没有这个arg上传,检查下载标题将显示正确的MIMEtypes)。
下载文件时收到的标题
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.dmg
和linux_file.zip
都是以扩展名下载的。 其他浏览器也不会受到影响 – 它们都是在S3中按原样下载文件。
我尝试过和没有AV礼物 – 这没有什么差别。
您需要正确设置content-disposition
:
使用HTTP标题强制SaveAs为了强制浏览器在单击超链接时显示SaveAs对话框,必须在要下载的文件的HTTP响应中包含以下标题:
Content-Disposition: attachment; filename="<file name.ext>"; filename*=utf-8''<file name.ext>
注意:那些不支持RFC 5987编码的用户代理在文件名后面忽略filename*
。
你想要在SaveAs对话框中显示的文件名在哪里(如finances.xls或mortgage.pdf) – 没有<
和>
符号。
你必须牢记以下几点:
< > \ " / : | ? *
空格。 古代的浏览器也需要以下(现在不需要,但是对于一个傻瓜式的解决方案来说可能是值得的):
所以,你应该使用cp
选项:
--content-type (string)
为此操作指定显式内容类型。 此值将覆盖任何猜测的MIME类型。 --content-disposition (string)
指定对象的表示信息。 --metadata-directive REPLACE
指定元数据是从源对象复制还是用复制S3对象时提供的元数据替换。 请注意,如果您正在使用以下任何参数:– --content-type
, content-language
,– --content-encoding
,– --content-disposition
,– --cache-control
或--expires
,则需要指定--metadata-directive REPLACE
如果希望复制的对象具有指定的元数据值,则对非多部分副本进行--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签名者提供了自己的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' })