Ras*_*ash 6 amazon-s3 laravel laravel-5 flysystem
在我使用laravel 5.1构建的web应用程序中,用户可以上传我存储在Amazon S3中的一些敏感文件.后来我希望用户WITH PERMISSION下载此文件.由于我希望进行此身份验证检查,因此我无法使用传统方法下载该文件,只需在S3中直接链接到文件即可.
我的方法:
当用户请求下载时,我的服务器在本地下载文件,然后流式传输给用户.问题:需要很长时间,因为文件有时太大.
为用户提供预先签名的URL,以便直接从S3下载.URL仅在5分钟内有效.问题:如果共享该URL,则任何人都可以在5分钟内下载该URL.
根据这篇文章,将数据直接从S3流式传输到客户端.这看起来很有希望,但我不知道如何实现这一点.
根据这篇文章,我需要:
S3Client对象,因为laravel使用flysystem,我不知道调用什么方法来获取这个对象.也许我需要在我的composer.json中单独包含S3包?我相信其他开发人员之前已经看过这样的问题,并希望得到一些帮助指针.如果有人已经使用laravel直接从S3流向客户端Response::download($pathToFile, $name, $headers),那么我很想听听你的方法.
通过评论中的讨论,我得出了一些我想分享的关键点.
Pre-Signed URLs
正如@ceejayoz所指出的,pre-signedURL并不是一个坏主意,因为:
cloud front,我也可以限制IP地址,增加更多的安全性.IAM Roles
他还指出了另一种不太好的方法 - 创建临时IAM用户.如果没有正确完成,这是一个维护噩梦,所以只有你知道自己在做什么才行.
Stream From S3
这是我现在选择的方法.也许以后我会转向第一种方法.
警告:如果您流式传输,那么您的服务器仍然是中间人,所有数据都将通过您的服务器传输.因此,如果它失败,或者速度很慢,那么下载速度会很慢.
我的第一个问题是 how to register stream wrapper:
由于我使用Laravel和laravel使用flysystem进行S3管理,因此我无法轻松获得S3Client.因此,我增加了额外的包AWS SDK for Laravel在我composer.json
"aws/aws-sdk-php-laravel" : "~3.0"
Run Code Online (Sandbox Code Playgroud)
然后我写了我的代码如下:
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}");
}
}
Run Code Online (Sandbox Code Playgroud)
我的第二个问题是 Do I need to Disable output buffering在laravel?
答案恕我直言是肯定的.缓冲使数据立即从缓冲区刷新,从而降低内存消耗.由于我们没有使用任何laravel函数将数据卸载到客户端,因此不能通过laravel完成,因此需要由我们完成.
| 归档时间: |
|
| 查看次数: |
2815 次 |
| 最近记录: |