使用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完成,因此需要由我们完成. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |