强制从 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 亚马逊服务器下载的主要内容,如果未能解决你的问题,请参考以下文章

从亚马逊s3桶下载文件的Javascript?

将文件从S3下载到EC2时出错

aws S3使用总结

我想使用android studio从亚马逊s3桶中删除一个文件

如何将画布数据 uri 上传到亚马逊 s3 服务器

亚马逊 s3 / 其他 AWS 服务上的操作日志