php Laravel League/flysystem 使用 AWS S3 获取文件 URL

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25323753/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 17:47:11  来源:igfitidea点击:

Laravel league/flysystem getting file URL with AWS S3

phplaravelamazon-s3package

提问by Ioana Cucuruzan

I am trying to build a file management system in Laravel based on league/flysystem: https://github.com/thephpleague/flysystem

我正在尝试基于 League/flysystem 在 Laravel 中构建一个文件管理系统:https: //github.com/thephpleague/flysystem

I am using the S3 adapter and I have it working to save the uploaded files using:

我正在使用 S3 适配器,并且可以使用以下方法保存上传的文件:

$filesystem->write('filename.txt', 'contents');

Now I am stuck on generating the download file URLwhen using the S3 adapter.

现在我坚持在使用 S3 适配器时生成下载文件 URL

The files are saved correctly in the S3 bucket, I have permissions to access them, I just don't know how to get to the S3 getObjectUrl method through the league/flysystem package.

文件正确保存在 S3 存储桶中,我有访问它们的权限,我只是不知道如何通过 League/flysystem 包访问 S3 getObjectUrl 方法。

I have tried:

我试过了:

$contents = $filesystem->read('filename.txt');

but that returns the content of the file.

但这会返回文件的内容。

$contents = $filemanager->listContents();

or

或者

$paths = $filemanager->listPaths();

but they give me the relative paths to my files.

但他们给了我文件的相对路径。

What I need is something like "ht...//[s3-region].amazonaws.com/[bucket]/[dir]/[file]..."

我需要的是“ht...//[s3-region].amazonaws.com/[bucket]/[dir]/[file]...”

采纳答案by Jeremy Lindblom

I'm not sure what the correctway of doing this is with Flysystem, but the underlying S3Clientobject has a method for doing that. You could do $filesystem->getAdapter()->getClient()->getObjectUrl($bucket, $key);. Of course, building the URL is as trivial as you described, so you don't really need a special method to do it.

我不确定使用 Flysystem 执行此操作的正确方法是什么,但底层S3Client对象有一种方法可以做到这一点。你可以做$filesystem->getAdapter()->getClient()->getObjectUrl($bucket, $key);。当然,构建 URL 与您描述的一样微不足道,因此您实际上并不需要特殊的方法来完成它。

回答by i906

I am using Laravel 5.2 and the code below seemed to work fine.

我使用的是 Laravel 5.2,下面的代码似乎工作正常。

Storage::cloud()->url('filename');

回答by Richard McLain

When updating to Laravel 5.1 this method no longer supported by the adapter. No in your config you must have the S3_REGION set or you will get a invalid hostname error and secondly I had to use the command as input to create the presignedRequest.

当更新到 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;
}

回答by Kevin Lee

Maybe I'm a little late to this question, but here's a way to use Laravel 5's built-in Filesystem.

也许我对这个问题有点晚了,但这里有一种使用 Laravel 5 的内置文件系统的方法。

I created a Manager class that extends Laravel's FilesystemManager to handle the public url retrieval:

我创建了一个 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);
    }
}

Then, I added this class to the AppServiceProvider under the register method so it has access to the current app instance:

然后,我将这个类添加到 AppServiceProvider 的 register 方法下,以便它可以访问当前的应用程序实例:

$this->app->singleton('filesystemPublicUrl', function () {
    return new FilesystemPublicUrlManager($this->app);
});

Finally, for easy static access, I created a Facade class:

最后,为了方便静态访问,我创建了一个 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';
    }
}

Now, I can easily get the public url for my public objects on my local and s3 filesystems (note that I didn't add anything for ftp or rackspace in the FilesystemPublicUrlManager):

现在,我可以轻松获取本地和 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');

回答by Greg

Another form of Storage::cloud():

另一种形式的 Storage::cloud():

    /** @var FilesystemAdapter $disk */
    $s3 = Storage::disk('s3');
    return $s3->url($path);