强制从 s3 亚马逊服务器下载
Posted
技术标签:
【中文标题】强制从 s3 亚马逊服务器下载【英文标题】:Forcing Download from s3 amazon servers 【发布时间】:2011-08-25 14:26:41 【问题描述】:我一直在开发一个新的 Web 应用程序,它依赖于 Amazon S3 服务器作为存储系统,Codeiginter 作为 php 框架。
点击链接时我需要强制下载文件。原始 URL 如下所示:
http://www.our-web.com/download/do/1.jpg
它会为 Amazon S3 服务器上的实际文件生成一个临时签名 URL,如下所示:
http://main_bucket.s3.amazonaws.com/post/1/1.jpg?AWSAccessKeyId=AKIAJEOQKYPKC3CCU5RA&Expires=1305395426&Signature=iuzCdA22gImLK192%2BMAhk8OkAY8%3D
我需要在用户点击链接后立即从真实的亚马逊 URL 开始下载文件。
我现在有两种方法:
-
使用
redirect()
打开文件不下载;或
将标题更改为以下代码:
header('Content-type: application/force-download');
header('Content-Disposition: attachment; filename=' . $file_name);
header('Content-Transfer-Encoding: binary');
header('Expires: 4000');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($generated_file));
readfile($generated_file);
不幸的是,这两种方式都对我没有帮助。第二种方法导致下载来自我的网站,而不是直接来自亚马逊。
如何强制文件直接从 Amazon S3 服务器下载,而不是从我的网站下载?
【问题讨论】:
使用 file_get_contents 或 cURL 检索 S3 文件,然后使用标头进行直通 这就是他对readfile
所做的。
正确,但即使我不希望客户端通过我的网站下载文件。从另一个域下载必须有更好的解决方案。
如果您尝试利用 cloudfront,则通过您的站点拉取文件是一个糟糕的主意,这可能会将您的内容分发到多达 19 个边缘节点。
【参考方案1】:
您只需在 S3 中为您的文件设置正确的标题,以强制浏览器下载而不是打开文件。设置这些:
Content-Disposition: attachment; filename=FILENAME.EXT
Content-Type: application/octet-stream
您需要在将文件上传到 S3 时进行设置。对于php SDK,您将使用create_object
。
或者您可以在使用'change_content_type' 或在S3 中通过copying the file to itself 上传并设置正确的标头后设置这些。
【讨论】:
它已通过更改文件元来解决,如以下代码所示:$opt['meta']['Content-Type'] = 'binary/octet-stream'; @Khaled - 太好了。很高兴为您提供帮助:) 我相信唯一真正需要的是内容处置标题。无需设置内容类型。【参考方案2】:聚会迟到了,但您通常不想在存储时决定如何使用文件。您希望能够将文件存储一次,然后在一个区域可能嵌入文件或显示在浏览器中,而在另一个区域使用户能够下载相同的文件。
幸运的是,您可以通过在请求 url 中提供覆盖参数来做到这一点。它仅适用于签名请求,但幸运的是您已经这样做了。
如果你添加一个像&request-content-type="application/force-download"
这样的参数应该可以解决问题。
查看 S3 GET 对象文档的 请求参数 部分: http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html
【讨论】:
我相信正确的请求参数是request-content-disposition=attachment; filename=FILENAME.EXT"
。您的 request-content-type
正在工作,因为它是未知的内容类型,因此浏览器默认下载它。
太棒了,是的,这就是我所追求的。宁愿在存储时不做决定(特别是因为 S3 中已经有数千个我不想修改的文件)。
截至 2019 年实际上是 response-content-disposition=attachment;%20FILENAME.EXT
卢克评论的文档docs.aws.amazon.com/AmazonS3/latest/API/…【参考方案3】:
问题是关于以编程方式设置,但要通过 AWS 控制台手动设置:
在 S3 中选择一个文件。 属性 > 元数据 > 添加更多元数据 键:Content-Disposition 值:附件 保存【讨论】:
非常有用,因为这个答案在谷歌搜索中排名很高,我需要向非技术人员展示如何在 AWS 上做到这一点。【参考方案4】:如果您的 S3 网站落后于 CloudFront,请不要忘记在重试之前使文件无效!这将清除缓存的文件。
您可以通过以下方式进入失效页面:
Cloudfront -> Distribution Settings -> Invalidation
然后输入文件的路径。
使文件无效需要一些时间。我的文件花了 5 分钟。
【讨论】:
【参考方案5】:您无法告诉浏览器如何处理远程文件。通过重定向到亚马逊,您是在告诉浏览器在那里开始一个新请求。您无法控制该请求。
我能想到的唯一解决方案是将图像打包成 zip 文件或类似文件。当然,这会增加另一种(可能是烦人的)复杂性。
【讨论】:
图片只是一个例子,可能我忘了提到几种文件类型是允许的,特别是pdf和docx。无论如何,感谢您的回复,但我认为有办法解决这个问题。实际上很多大网站都使用外部存储系统。 我不知道在将文件上传到 S3 时设置标题的可能性。很高兴知道。 有可能,我认为亚马逊还没有提供更好的解决方案,我们之所以选择亚马逊 s3,是因为它可以直接从浏览器使用 POST 直接上传。无论如何感谢您的帮助以上是关于强制从 s3 亚马逊服务器下载的主要内容,如果未能解决你的问题,请参考以下文章