[英]Laravel league/flysystem getting file URL with AWS S3
我正在尝试基于 League/flysystem 在 Laravel 中构建一个文件管理系统: https : //github.com/thephpleague/flysystem
我正在使用 S3 适配器,并且可以使用以下方法保存上传的文件:
$filesystem->write('filename.txt', 'contents');
现在我坚持在使用 S3 适配器时生成下载文件 URL 。
文件正确保存在 S3 存储桶中,我有访问它们的权限,我只是不知道如何通过 League/flysystem 包访问 S3 getObjectUrl 方法。
我试过了:
$contents = $filesystem->read('filename.txt');
但这会返回文件的内容。
$contents = $filemanager->listContents();
或者
$paths = $filemanager->listPaths();
但他们给了我文件的相对路径。
我需要的是“ht...//[s3-region].amazonaws.com/[bucket]/[dir]/[file]...”
我使用的是 Laravel 5.2,下面的代码似乎工作正常。
Storage::cloud()->url('filename');
我不确定使用 Flysystem 执行此操作的正确方法是什么,但底层的S3Client
对象有一种方法可以做到这一点。 你可以做$filesystem->getAdapter()->getClient()->getObjectUrl($bucket, $key);
. 当然,构建 URL 与您描述的一样微不足道,因此您实际上并不需要特殊的方法来完成它。
当更新到 Laravel 5.1 时,适配器不再支持此方法。 不,在您的配置中,您必须设置 S3_REGION,否则您将收到无效的主机名错误,其次我必须使用该命令作为输入来创建 presignedRequest。
public function getFilePathAttribute($value)
{
$disk = Storage::disk('s3');
if ($disk->exists($value)) {
$command = $disk->getDriver()->getAdapter()->getClient()->getCommand('GetObject', [
'Bucket' => Config::get('filesystems.disks.s3.bucket'),
'Key' => $value,
'ResponseContentDisposition' => 'attachment;'
]);
$request = $disk->getDriver()->getAdapter()->getClient()->createPresignedRequest($command, '+5 minutes');
return (string) $request->getUri();
}
return $value;
}
也许我对这个问题有点晚了,但这里有一种使用 Laravel 5 的内置文件系统的方法。
我创建了一个 Manager 类,它扩展了 Laravel 的 FilesystemManager 来处理公共 url 检索:
class FilesystemPublicUrlManager extends FilesystemManager
{
public function publicUrl($name = null, $object_path = '')
{
$name = $name ?: $this->getDefaultDriver();
$config = $this->getConfig($name);
return $this->{'get' . ucfirst($config['driver']) . 'PublicUrl'}($config, $object_path);
}
public function getLocalPublicUrl($config, $object_path = '')
{
return URL::to('/public') . $object_path;
}
public function getS3PublicUrl($config, $object_path = '')
{
$config += ['version' => 'latest'];
if ($config['key'] && $config['secret']) {
$config['credentials'] = Arr::only($config, ['key', 'secret']);
}
return (new S3Client($config))->getObjectUrl($config['bucket'], $object_path);
}
}
然后,我将这个类添加到 AppServiceProvider 的 register 方法下,以便它可以访问当前的应用程序实例:
$this->app->singleton('filesystemPublicUrl', function () {
return new FilesystemPublicUrlManager($this->app);
});
最后,为了方便静态访问,我创建了一个 Facade 类:
use Illuminate\Support\Facades\Facade;
class StorageUrl extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'filesystemPublicUrl';
}
}
现在,我可以轻松获取本地和 s3 文件系统上公共对象的公共 url(请注意,我没有在 FilesystemPublicUrlManager 中为 ftp 或 rackspace 添加任何内容):
$s3Url = StorageUrl::publicUrl('s3') //using the s3 driver
$localUrl = StorageUrl::publicUrl('local') //using the local driver
$defaultUrl = StorageUrl::publicUrl() //default driver
$objectUrl = StorageUrl::publicUrl('s3', '/path/to/object');
另一种形式的 Storage::cloud():
/** @var FilesystemAdapter $disk */
$s3 = Storage::disk('s3');
return $s3->url($path);
对于私有云,使用这个
Storage::disk('s3')->temporaryUrl($path);
使用预签名请求 S3:
public function getFileUrl($key) {
$s3 = Storage::disk('s3');
$client = $s3->getDriver()->getAdapter()->getClient();
$bucket = env('AWS_BUCKET');
$command = $client->getCommand('GetObject', [
'Bucket' => $bucket,
'Key' => $key
]);
$request = $client->createPresignedRequest($command, '+20 minutes');
return (string) $request->getUri();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.