使用Laravel从Web服务器流式传输Amazon S3对象
|
在我使用laravel 5.1构建的web应用程序中,用户可以上传我存储在Amazon S3中的一些敏感文件.后来我希望用户WITH PERMISSION下载此文件.由于我希望进行此身份验证检查,因此我无法使用传统方法下载该文件,只需在S3中直接链接到文件即可.
我的方法: >当用户请求下载时,我的服务器在本地下载文件,然后流式传输给用户.问题:需要很长时间,因为文件有时太大. 根据这篇文章,我需要: >注册流包装 – 这是我的第一个问题,因为我不知道如何获取S3Client对象,因为laravel使用flysystem,我不知道调用什么方法来获取这个对象.也许我需要在我的composer.json中单独包含S3包? 我相信其他开发人员之前已经看过这样的问题,并希望得到一些帮助指针.如果有人已经使用laravel Response :: download($pathToFile,$name,$headers)直接从S3流向客户端,那么我很想听听你的方法. 解决方法
通过评论中的讨论,我得出了一些我想分享的关键点.
预签名网址 正如@ceejayoz指出的那样,预先签名的URL并不是一个坏主意,因为: >我可以保持时间低至10秒,这对于任何重定向和开始下载都是完美的,但不足以让链接被共享. IAM角色 他还指出了另一种不太好的方法 – 创建临时IAM用户.如果没有正确完成,这是一个维护噩梦,所以只有你知道自己在做什么才行. 来自S3的流 这是我现在选择的方法.也许以后我会转向第一种方法. 警告:如果您流式传输,那么您的服务器仍然是中间人,所有数据都将通过您的服务器传输.因此,如果它失败,或者速度很慢,那么下载速度会很慢. 我的第一个问题是如何注册流包装器: 由于我使用Laravel和laravel使用flysystem进行S3管理,因此我无法轻松获得S3Client.因此,我在composer.json中为Laravel添加了额外的包AWS SDK "aws/aws-sdk-php-laravel" : "~3.0" 然后我写了我的代码如下: class FileDelivery extends Command implements SelfHandling
{
private $client;
private $remoteFile;
private $bucket;
public function __construct($remoteFile)
{
$this->client = AWS::createClient('s3');
$this->client->registerStreamWrapper();
$this->bucket = 'mybucket';
$this->remoteFile = $remoteFile;
}
public function handle()
{
try
{
// First get the meta-data of the object.
$headers = $this->client->headObject(array(
'Bucket' => $this->bucket,'Key' => $this->remoteFile
));
$headers = $headers['@metadata'];
if($headers['statusCode'] !== 200)
{
throw new S3Exception();
}
}
catch(S3Exception $e)
{
return 404;
}
// return appropriate headers before the stream starts.
http_response_code($headers['statusCode']);
header("Last-Modified: {$headers['headers']['last-modified']}");
header("ETag: {$headers['headers']['etag']}");
header("Content-Type: {$headers['headers']['content-type']}");
header("Content-Length: {$headers['headers']['content-length']}");
header("Content-Disposition: attachment; filename="{$this->filename}"");
// Since file sizes can be too large,// buffers can suffer because they cannot store huge amounts of data.
// Thus we disable buffering before stream starts.
// We also flush anything pending in buffer.
if(ob_get_level())
{
ob_end_flush();
}
flush();
// Start the stream.
readfile("s3://{$this->bucket}/{$this->remoteFile}");
}
}
我的第二个问题是我是否需要在laravel中禁用输出缓冲? 答案恕我直言是肯定的.缓冲使数据立即从缓冲区刷新,从而降低内存消耗.由于我们没有使用任何laravel函数将数据卸载到客户端,因此不能通过laravel完成,因此需要由我们完成. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
