使用 Filesystem Laravel 5.2 从 amazon s3 获取文件的签名 URL

Posted

技术标签:

【中文标题】使用 Filesystem Laravel 5.2 从 amazon s3 获取文件的签名 URL【英文标题】:Get file's signed URL from amazon s3 using Filesystem Laravel 5.2 【发布时间】:2016-07-09 08:00:41 【问题描述】:

我正在寻找一个从 amazon s3 获取签名网址的好解决方案。

我有一个可以使用它的版本,但没有使用 laravel:

private function getUrl ()

        $distribution = $_SERVER["AWS_CDN_URL"];

        $cf = Amazon::getCFClient();

        $url = $cf->getSignedUrl(array(
            'url'     => $distribution . self::AWS_PATH.rawurlencode($this->fileName),
            'expires' => time() + (session_cache_expire() * 60)));

        return $url;

我不知道这是否是使用 laravel 的最佳方式,考虑到它有一个完整的文件系统可以工作......

但是如果没有其他方法,我该如何获得客户?调试我在 Filesystem 对象中找到了它的一个实例,但它是受保护的......

【问题讨论】:

在 Laravel 5.5 中有一个 temporaryUrl 方法可以用于 S3 laravel.com/docs/5.5/filesystem#file-urls 【参考方案1】:

在 Laravel 中,

$s3 = \Storage::disk('s3');
$client = $s3->getDriver()->getAdapter()->getClient();
$expiry = "+10 minutes";

$command = $client->getCommand('GetObject', [
    'Bucket' => \Config::get('filesystems.disks.s3.bucket'),
    'Key'    => "file/in/s3/bucket"
]);

$request = $client->createPresignedRequest($command, $expiry);

return (string) $request->getUri();

确保您也有 AWS for flysystem composer 包(版本会有所不同):

"league/flysystem-aws-s3-v3": "1.0.9"

【讨论】:

从this pull 开始,我看到这段代码(或其危险的接近版本)现在是 Laravel 的一部分。文档 [up as well] (laravel.com/docs/5.5/filesystem#file-visibility)(查找 ::temporaryUrl)。【参考方案2】:

对于 Laravel 5.5 及更高版本, 您现在可以使用临时 URLs/s3 预签名 URL。

use \Storage;

// Make sure you have s3 as your disk driver
$url = Storage::disk('s3')->temporaryUrl(
   'file1.jpg', Carbon::now()->addMinutes(5)
);

这仅适用于 s3 存储驱动程序 AFAIK。

https://laravel.com/docs/5.5/filesystem#retrieving-files

【讨论】:

这很好,但我必须指定存储为 S3 以避免出现异常“此驱动程序不支持创建临时 URL。”。例如:$url = Storage::disk('s3')->temporaryUrl( ... );. 由于@pnairn,我还需要指定s3 以避免异常 如果 s3 文件使用 CloudFront,您有什么不同的做法?我能够使用上述方法为 S3 生成签名 URL,但我想使用云端 URL。这可能吗?【参考方案3】:

经过大量的bug,我终于找到了使用以下代码访问s3存储桶私有内容的解决方案:-

use Storage;
use Config;

$client = Storage::disk('s3')->getDriver()->getAdapter()->getClient();
$bucket = Config::get('filesystems.disks.s3.bucket');

$command = $client->getCommand('GetObject', [
    'Bucket' => $bucket,
    'Key' => '344772707_360.mp4'  // file name in s3 bucket which you want to access
]);

$request = $client->createPresignedRequest($command, '+20 minutes');

// Get the actual presigned-url
echo $presignedUrl = (string)$request->getUri();

【讨论】:

【参考方案4】:

上面的解释答案(@brian_d)是可以的,但是生成预签名的url需要太多时间。我浪费了将近 4-5 天来克服这个问题。终于跟随为我工作了。感谢@Kenth。

use Carbon\Carbon;
use Illuminate\Support\Facades\Storage;

$disk = Storage::disk('s3');
$url = $disk->getAwsTemporaryUrl($disk->getDriver()->getAdapter(), $value, Carbon::now()->addMinutes(5), []);

【讨论】:

【参考方案5】:

这是将图片上传到 S3 并创建签名 URL 的完整代码;

首先,获取一个文件对象并创建对象名

$filename = $_FILES["image"]["name"];
$array = explode('.', $filename);
$fileExt = $array[1]; // to get file extension
$objectName = 'images/' . time() .$fileExt; // create object name
$document = fopen($_FILES["image"]["tmp_name"],'r');

// Code to upload document on s3
$s3 = \Storage::disk('s3');
$s3->put($objectName,$document,'public');

// If you want to get uploaded document Url you can use below code:
$image_name = \Storage::disk('s3')->url($name); // it will return stored document url

创建/获取签名 URL 的代码,你也可以把它作为一个单独的函数:

$s3 = \Storage::disk('s3');
$client = $s3->getDriver()->getAdapter()->getClient();
$expiry = "+10 minutes";

$command = $client->getCommand('GetObject', [
  'Bucket' => config('params.YOUR_AWS_BUCKET_NAME'), // bucket name
  'Key'    => $objectName
]);

$request = $client->createPresignedRequest($command, $expiry);
$url =  (string) $request->getUri(); // it will return signed URL

【讨论】:

【参考方案6】:
$file_path = "profile/image.png";

$client = Storage::disk('s3')->getDriver()->getAdapter()->getClient();

$bucket = config('filesystems.disks.s3.bucket');
$command = $client->getCommand('GetObject', [
        'Bucket' => $bucket,
        'Key' => $file_path  // file name in s3 bucket which you want to access
    ]);
$request = $client->createPresignedRequest($command, '+5 minutes');

return $presignedUrl = (string) $request->getUri(); // Get the actual presigned-url

【讨论】:

以上是关于使用 Filesystem Laravel 5.2 从 amazon s3 获取文件的签名 URL的主要内容,如果未能解决你的问题,请参考以下文章

打印 laravel Blade 的内容(使用 Laravel 5.2)

Laravel 5.2 - 使用数组过滤

如何使用 5.2 版本在本地运行 laravel 项目

如何在 Laravel 5.2 中使用资源声明路由

Laravel 5.2 - 使用 composer 和 git bash 安装 laravel 时出错

硒和 Laravel 5.2