在php中,我希望将s3文件下载到浏览器,而不将其存储在服务器上

在php中,我希望将s3文件下载到浏览器,而不将其存储在服务器上,php,download,amazon-s3,fopen,buffering,Php,Download,Amazon S3,Fopen,Buffering,我有亚马逊S3上的文件。它们使用唯一的ID命名,因此不存在重复项。我正在使用授权的URL访问它们。我需要能够将它们传递到浏览器,但我需要重命名它们。现在我正在使用fopen,但它正在将文件下载到我的服务器,然后再将文件提供给浏览器。如何让文件“通过”我的服务器进入浏览器?或者我如何缓冲下载-下载一小块到我的服务器,并在下载下一块时将其传递到浏览器 另外,我真的很想使用CloudFront,但他们不提供经过验证的URL。我相信我可以使用CURL来发送请求的凭据——我可以用CURL做这种“传递”文件

我有亚马逊S3上的文件。它们使用唯一的ID命名,因此不存在重复项。我正在使用授权的URL访问它们。我需要能够将它们传递到浏览器,但我需要重命名它们。现在我正在使用fopen,但它正在将文件下载到我的服务器,然后再将文件提供给浏览器。如何让文件“通过”我的服务器进入浏览器?或者我如何缓冲下载-下载一小块到我的服务器,并在下载下一块时将其传递到浏览器

另外,我真的很想使用CloudFront,但他们不提供经过验证的URL。我相信我可以使用CURL来发送请求的凭据——我可以用CURL做这种“传递”文件服务吗


谢谢

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


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

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

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

  • -实现对HTTP资源的请求的类(由下面的流包装器使用)。允许对请求进行流式处理
  • -一个HTTP流包装器,允许您使用诸如
    fopen()
    fread()
    等函数将远程HTTP资源视为文件
  • -由与gHttp相同的开发人员开发的Amazon S3流包装器。还允许通过
    fopen('s3://…')
    像访问普通文件一样访问远程资源

编辑:

具有有关如何通过在URL中编码身份验证密钥来“预验证”请求的信息。它位于标题为“查询字符串请求身份验证备选方案”的部分下


然后将用户重定向到
$url
,他们就可以下载文件了。签名由单向加密方案(sha1)编码,因此您的AWS秘密访问密钥不会被发现。

您是否尝试过使用readfile(“”)

这将只是绕过并直接写入outputbuffer,但是,如果内容类型有问题,您需要首先验证它


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

谢谢,Joe。我会调查的。我对重定向的一个担心是,你需要验证你的安全性没有被传递。如果重定向需要授权,那么您将授权给客户端。这就是生成临时公共URL的原因。这样就不会传递任何身份验证信息,而且一旦用户收到文件(或在某个时间限制之后),URL就会消失。我认为这并不能解决我的重命名风险。如果我把两个文件移到一个公共文件夹中,以便直接下载,我必须在那里给它们起一个友好的名字。有可能他们有相同的名字,然后我被卡住了。S3就是这样工作的吗?我认为web URL是动态生成的,并且与文件系统完全分离?据我所知,每个托管文件可以有多个web URL。@Calvin-是的,您可以为s3创建经过身份验证的URL。你需要多少就有多少。但我认为您的解决方案是正确的——重定向,因为这样我就可以重定向到cloudfront URL。我的下一个问题是,我可以在标题中使用身份验证信息重定向吗?
// 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;