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

Ioa*_*zan 16 php amazon-s3 package laravel

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

我正在使用S3适配器,我使用它来保存上传的文件:

$filesystem->write('filename.txt', 'contents');
Run Code Online (Sandbox Code Playgroud)

现在,我在使用S3适配器时无法生成下载文件URL.

文件在S3存储桶中正确保存,我有权访问它们,我只是不知道如何通过联盟/ flysystem包获得S3 getObjectUrl方法.

我试过了:

$contents = $filesystem->read('filename.txt');
Run Code Online (Sandbox Code Playgroud)

但是它返回文件的内容.

$contents = $filemanager->listContents();
Run Code Online (Sandbox Code Playgroud)

要么

$paths = $filemanager->listPaths();
Run Code Online (Sandbox Code Playgroud)

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

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

i90*_*906 28

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

Storage::cloud()->url('filename');
Run Code Online (Sandbox Code Playgroud)

  • 这至少应该是Laravel> = 5.2中的正确答案.Cloud组在config/filesystems.php中配置,默认为's3' (3认同)

Jer*_*lom 12

我不确定使用Flysystem这样做的正确方法是什么,但底层S3Client对象有一个方法可以做到这一点.你可以做到$filesystem->getAdapter()->getClient()->getObjectUrl($bucket, $key);.当然,构建URL与您描述的一样简单,因此您不需要特殊的方法来执行此操作.

  • 这仅适用于您的S3文件可公开访问的情况 (6认同)
  • @andrewtweber不正确.如果我在S3上将资产设为私有,并且我在S3上授予某个用户或组的查看权限,然后我为在我的Web应用程序中被授予权限的用户/组使用API​​令牌,那么Web应用程序可以访问文件,即使它们对其他人都是私有的.或者,我可以锁定所有资产并使我的域能够通过S3中的CORS设置查看资产. (5认同)

小智 9

更新到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;
}
Run Code Online (Sandbox Code Playgroud)


Kev*_*Lee 6

也许我对这个问题有点迟了,但是这里有一种使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

$this->app->singleton('filesystemPublicUrl', function () {
    return new FilesystemPublicUrlManager($this->app);
});
Run Code Online (Sandbox Code Playgroud)

最后,为了便于静态访问,我创建了一个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';
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我可以轻松地在我的本地和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');
Run Code Online (Sandbox Code Playgroud)