Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何在Laravel 5中获取上载文件的公共url_Php_Laravel_Filesystems - Fatal编程技术网

Php 如何在Laravel 5中获取上载文件的公共url

Php 如何在Laravel 5中获取上载文件的公共url,php,laravel,filesystems,Php,Laravel,Filesystems,您可能知道,Laravel使用Flysystem PHP包来提供文件系统抽象。 我开始在我的项目中使用这个功能,只是为了好玩,我上传了一些图片到我的AmazonS3存储桶,我还将Cloudfront的实例链接到这个存储桶。我的问题是,当我试图在我的html页面中显示这些图像时,我需要一个url 我找不到任何“干净”的方法来做这件事,因为flysystem是一个通用的库,我认为我将能够做这样的事情: Storage::disk('my_awesome_disk')->publicUrl("{

您可能知道,Laravel使用Flysystem PHP包来提供文件系统抽象。 我开始在我的项目中使用这个功能,只是为了好玩,我上传了一些图片到我的AmazonS3存储桶,我还将Cloudfront的实例链接到这个存储桶。我的问题是,当我试图在我的html页面中显示这些图像时,我需要一个url

我找不到任何“干净”的方法来做这件事,因为flysystem是一个通用的库,我认为我将能够做这样的事情:

Storage::disk('my_awesome_disk')->publicUrl("{$path}/{$image->name}")
对于“public”文件,很容易确定文件是否为“public”,因为它包含在api中,因此如果我使用s3 bucket作为磁盘的驱动程序,我应该得到: “”

或者:

Storage::disk('my_awesome_disk')->signedUrl("{$path}/{$image->name}", $timeout)
对于“私有”文件-我应该得到一个临时url,该url将在一段时间后过期

这是我只有通过具体实施才能实现的吗?例如,如果我使用Amazon S3,我可以轻松运行:

$signed_url = $s3Client->getObjectUrl($bucket_name,
                        $resource_key,
                        "+{$expires} minutes");
但我不想用丑陋的“开关箱”来确定我用的是什么驱动程序。 我如何通过文件系统接口从cdn(如cloudfront)获取url?
有什么建议吗?

我认为Flysystem只是一个磁盘(或其他存储机制)的接口而已。正如我不会要求本地文件系统计算公共URI一样,我也不会要求
Flysystem
这样做

我创建与通过
Flysystem
保存的文件相对应的对象。根据需要,我可以将公共URI直接保存在数据库记录中,或者创建一个自定义getter,根据运行时环境构建公共URI

使用
Flysystem
,我在编写文件时知道文件的路径。为了跟踪这些文件,我通常会创建一个表示已保存文件的对象:

class SavedFile extends Model
{
    protected $fillable = [
        'disk',
        'path',
        'publicURI',
    ];
}
保存文件时,我会在数据库中创建该文件的记录:

$disk     = 'local_example';
$path     = '/path/to/file.txt';
$contents = 'lorem ipsum';
$host     = 'https://example.com/path/to/storage/root/';

if (Store::disk($disk)->put($path, $contents)) {
    SavedFile::create([
        'disk'      => $disk,
        'path'      => $path,
        'publicURI' => $host . $path,
    ]);
}
每当我需要公共URI时,我都可以从
SavedFile
模型中获取它。这对于普通的应用程序来说很方便,但是如果我需要切换存储提供程序,它就会崩溃

利用继承 另一个巧妙的技巧是定义一个方法,该方法将根据抽象
SavedFile
模型的子级中定义的变量解析公共URI。这样,我就不用在数据库中硬编码URI,我可以为其他存储服务创建新的类,只需几个变量定义:

abstract class SavedFile extends Model
{
    protected $table = 'saved_files';

    protected $disk;

    protected $host;

    protected $fillable = [
        'path',
    ];

    public function getPublicURIAttribute()
    {
        return $this->host . $this->attributes['path'];
    }
}

class LocalSavedFile extends SavedFile
{
    $disk = 'local_example';
    $host = 'https://example.com/path/to/storage/root';
}

class AwsSavedFile extends SavedFile
{
    $disk = 'aws_example';
    $host = 'https://s3.amazonaws.com/my_awesome_bucket';
}
现在,如果我有一堆文件存储在本地文件系统中,有一天我将它们移动到AmazonS3,我就可以简单地复制这些文件并交换IoC绑定定义中的依赖项,我就完成了。无需在海量数据库表上执行耗时且具有潜在危险的查找和替换,因为URI的计算是由模型完成的:

$localFile = LocalSavedFile::create([
    'path' => '/path/to/file.txt'
]);
echo $localFile->publicURI; // https://example.com/path/to/storage/root/path/to/file.txt

$awsFile = AwsSavedFile::find($localFile->id);
echo $awsFile->publicURI; // https://s3.amazonaws.com/my_awesome_bucket/path/to/file.txt
编辑:

支持公共和私有文件 只需向对象添加一个标志:

abstract class SavedFile extends Model
{
    protected $table = 'saved_files';

    protected $disk;

    protected $host;

    protected $fillable = [
        'path',
        'public',
    ];

    public function getPublicURIAttribute()
    {
        if ($this->attributes['public'] === false) {
            // you could throw an exception or return a default image if you prefer
            return false;
        }

        return $this->host . $this->attributes['path'];
    }
}

class LocalSavedFile extends SavedFile
{
    $disk = 'local_example';
    $host = 'https://example.com/path/to/storage/root';
}

$localFile = LocalSavedFile::create([
    'path'   => '/path/to/file.txt',
    'public' => false,
]);
var_dump($localFile->publicURI); // bool(false)

你做到了吗?我正在努力,我想我必须编写一个库来处理它,使用decorator设计模式扩展当前的api。在考虑系统设计时仍然有困难。当我假设我的所有文件都是公共文件时,这很可怕,但事实并非如此。我在这里看到的问题是使用绝对url,这是切换服务器时在产品环境中很难处理的问题。我用一个可能的解决方案编辑了我的答案:在
SavedFile
对象中添加一个标志。