【问题标题】:In php, I want to download an s3 file to the browser without storing it on my server在php中,我想将s3文件下载到浏览器而不将其存储在我的服务器上
【发布时间】:2010-10-20 19:49:43
【问题描述】:

我在 Amazon 的 S3 上有文件。它们以唯一的 ID 命名,因此没有重复项。我正在使用授权的 URL 访问它们。我需要能够将它们传递给浏览器,但我需要重命名它们。现在我正在使用 fopen,但它在将文件提供给浏览器之前将文件下载到我的服务器。我怎样才能让文件“通过”我的服务器到浏览器?或者我如何缓冲下载 - 将一小块下载到我的服务器并在下载下一个块时将其传递给浏览器?

另外 - 我真的很想使用 CloudFront,但他们不提供经过身份验证的 URL。我相信我可以使用 CURL 发送请求的凭据 - 我可以使用 CURL 执行这种“传递”文件吗?

谢谢!

【问题讨论】:

    标签: php download amazon-s3 fopen buffering


    【解决方案1】:

    我不熟悉 S3 的工作原理,所以我不知道这个解决方案是否可行。但是您不能简单地将用户的浏览器重定向到该文件吗?如果我理解正确,S3 允许您为存储桶中的任何文件创建 Web URL。因此,如果这些是付费下载,那么您可以have S3 generate a temporary URL for that download,然后在用户下载后将其删除。

    如果这不是一个选项,您可以尝试这些 PHP 类:

    • HTTP protocol client - 实现对 HTTP 资源的请求的类(由以下流包装器使用)。允许流式传输请求。
    • gHttp - 一个 HTTP 流包装器,可让您使用 fopen()fread() 等函数将远程 HTTP 资源视为文件。
    • Amazon S3 Stream Wrapper - 由与 gHttp 相同的开发人员开发的 Amazon S3 流包装器。还允许通过fopen('s3://...') 像普通文件一样访问远程资源。

    编辑:

    This page 包含有关如何通过在 URL 中编码身份验证密钥来“预身份验证”请求的信息。它位于标题为:Query String Request Authentication Alternative 的部分下。

    // I'm only implementing the parts required for GET requests.
    // POST uploads will require additional components.
    function getStringToSign($req, $expires, $uri) {
       return "$req\n\n\n$expires\n$uri";
    }
    
    function encodeSignature($sig, $key) {
        $sig = utf8_encode($sig);
        $sig = hash_hmac('sha1', $sig, $key);
        $sig = base64_encode($sig);
        return urlencode($sig);
    }
    
    $expires = strtotime('+1 hour');
    $stringToSign = getStringToSign('GET', $expires, $uri);
    $signature = encodeSignature($stringToSign, $awsKey);
    
    $url .= '?AWSAccessKeyId='.$awsKeyId
           .'&Expires='.$expires
           .'&Signature='.$signature;
    

    然后只需将用户重定向到$url,他们应该能够下载该文件。签名由单向加密方案 (sha1) 编码,因此您的 AWS 秘密访问密钥不会被泄露。

    【讨论】:

    • 我对重定向的一个担心是您需要验证您的安全性没有被传递。如果重定向需要授权,您将授权给客户端。
    • 嗯,这就是生成临时公共 URL 的原因。这样就不会传递任何身份验证信息,并且一旦用户收到文件(或在一定时间限制之后),URL 就会消失。
    • 我认为这不能解决我的重命名风险。如果我将两个文件移动到公用文件夹以允许直接下载,我必须在那里给它们起友好的名称。有可能他们有相同的名字,然后我就卡住了。
    • S3 是这样工作的吗?我认为 web url 是动态生成的并且完全与文件系统分离?据我了解,每个托管文件可以有多个网址。
    • @Calvin - 是的,您为 s3 创建了经过身份验证的 url。您可以根据需要拥有任意数量。但我认为您的解决方案是正确的 - 重定向,因为这样我可以重定向到云端 URL。我的下一个问题是我可以在标头中使用身份验证信息进行重定向吗?
    【解决方案2】:

    您是否尝试过使用 http_get 和 request_options 来指定 httpauth 和 httpauthtype?虽然我不记得这个方法是否假定字符串有效类型,这可能不适用于二进制。

    如果成功,那么您应该能够提供正确的 MIME 类型并写入浏览器。

    【讨论】:

    • 谢谢,乔。我会调查的。
    【解决方案3】:

    您是否尝试过仅使用 readfile("http://username:password@host/filename.ext") ?

    这只会绕过并直接写入输出缓冲区,但是如果您需要先验证内容类型。

    使用 en URL 作为 readfile 的参数还需要使用 urlwrapper-support 编译 PHP。

    【讨论】:

      猜你喜欢
      • 2020-10-17
      • 1970-01-01
      • 2018-04-24
      • 2015-07-29
      • 1970-01-01
      • 1970-01-01
      • 2012-12-08
      • 2016-02-19
      • 1970-01-01
      相关资源
      最近更新 更多