如何在Laravel 5中使用Storage Facade获取文件URL?


82

我一直在尝试将新的Flysystem与Laravel 5集成在一起。我正在将“本地化”路径存储到数据库,并让Storage Facade来完成路径。例如我存储screenshots/1.jpg和使用

Storage::disk('local')->get('screenshots/1.jpg')

要么

Storage::disk('s3')->get('screenshots/1.jpg') 

我可以在不同的磁盘上检索相同的文件。

get 检索文件内容,但我希望在我的视图中使用它:

<img src="{{ Storage::path('screenshots/1.jpg') }}" />

但是路径,或者任何能够检索完整路径的东西都不可用(据我所知)。那么如何返回完整路径?或者,我想知道这是否是设计使然?如果是这样,为什么我不应该获得完整的路径?还是我完全以错误的方式来做这件事?


1
您要的是网址,而不是路径。
亚当

Answers:


54

编辑:L5.2 +的解决方案

有一个更好,更直接的解决方案。

使用Storage::url($filename)得到给定文件的完整路径/ URL。请注意,您需要在中将设置S3为存储文件系统config/filesystems.php'default' => 's3'

当然,您也可以Storage::disk('s3')->url($filename)以相同的方式进行操作。

如您所见,config/filesystems.php还有一个'cloud' => 's3'定义的参数,它指向Cloud文件系统。如果您想保留本地服务器中的存储文件夹,但要在云使用中检索/存储一些文件,该文件Storage::cloud()也具有相同的文件系统方法,即Storage::cloud()->url($filename)

Laravel文档没有提到此方法,但是如果您想了解更多有关此方法的信息,可以在此处查看其源代码。


真好!这是一种新方法,但我很高兴现在就在这里!默认情况下,Storage类是否在视图中工作?如果是这样,请将其标记为正确答案。
daviestar

是!默认情况下,它在您的视图中起作用,因此您完全不必担心它。
Pere Joan Martorell,2016年

5
这是针对L5.2 +
daviestar '16

153

您的存储磁盘的路径为:

$storagePath  = Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix()

我不知道有什么更短的解决方案...

您可以共享$ storagePath到您的视图,然后调用

$storagePath."/myImg.jpg";

这是获取公共存储文件夹路径的理想解决方案。谢谢!
大卫

14
另一种方式是这样使用applyPathPrefixStorage::disk('local')->getDriver()->getAdapter()->applyPathPrefix('myImg.jpg');
Maxim Lanin 16'Sep

3
@maximLanin:如果您以某种方式复制示例,则最后一个(applyPathPrefix)在h和P(路径*前缀)之间有一个奇怪的字符。如果复制粘贴,将会出现错误。applyPathPrefix您可以复制的第一个。很奇怪。(您可以通过双击示例中的最后一个方法名称进行测试
Maurice

3
getDriver()不需要。完全Storage::disk('local')->getAdapter()->getPathPrefix()可以正常工作。
RA。

6
也许很高兴知道,自Laravel 5.4以来,有一种新的简单方法Storage::path,请参见Bilal的答案
Marten Koetsier

69

从Laravel 5.4开始存在此方法,您可以通过以下方法获取它:

$path = Storage::disk('public')->path($filename);

1
在Laravel 5.6中像吊饰一样工作。如果这一个API中有人奇观,这里是:laravel.com/api/5.6/Illuminate/Filesystem/...
天使圣地亚哥海梅·萨瓦拉

1
据我所知,此方法自Laravel 5.4(laravel.com/api/5.4/Illuminate/Filesystem/…
Marten Koetsier,

以上两个注释中的两个链接均已失效。
dotNET

9

这就是我的工作方式-使用环境变量在s3和本地目录路径之间切换,并将路径传递给所有视图。

在.env中:

APP_FILESYSTEM=local or s3
S3_BUCKET=BucketID

在config / filesystems.php中:

'default' => env('APP_FILESYSTEM'),

app/Providers/AppServiceProvider

public function boot()
{
    view()->share('dynamic_storage', $this->storagePath());
}

protected function storagePath()
{
    if (Storage::getDefaultDriver() == 's3') {
        return Storage::getDriver()
                ->getAdapter()
                ->getClient()
                ->getObjectUrl(env('S3_BUCKET'), '');
    }

    return URL::to('/');
}

1
使用描述的s3存储对我产生了错误。因此,我修改了此示例 return Storage::disk('s3')->getDriver()->getAdapter()->getClient()->getObjectUrl(env('S3_BUCKET'), '').'/';
Lionel Morrison

4

好吧,几周前,我提出了一个非常类似的问题(通过存储设备从上传的文件中获取CDN网址):我希望CDN网址在我的视图中显示图像(根据您的要求)。

但是,在查看了包API之后,我确认没有办法执行此任务。因此,我的解决方案是避免使用flysystem。就我而言,我需要玩RackSpace。因此,最后决定使用适用于OpenStack的PHP SDK创建我的使用包并制作自己的存储包。

通过这种方式,您可以完全访问所需的功能,getPublicUrl()以便从cdn容器获取公共URL:

/** @var DataObject $file */
$file = \OpenCloud::container('cdn')->getObject('screenshots/1.jpg');

// $url:  https://d224d291-8316ade.ssl.cf1.rackcdn.com/screenshots/1.jpg
$url = (string) $file->getPublicUrl(UrlType::SSL);

总之,如果需要将存储服务提升到另一个层次,那就flysystem远远不够。为此local,您可以尝试@nXu的解决方案


4

首先获取文件的URL /链接,然后获取路径,如下所示:

$url = Storage::disk('public')->url($filename);
$path = public_path($url);

4

如果只想显示存储(磁盘)路径,请使用以下命令:

Storage::disk('local')->url('screenshots/1.jpg'); // storage/screenshots/1.jpg
Storage::disk('local')->url(''): // storage

另外,如果您有兴趣,我为Laravel创建了一个包(https://github.com/fsasvari/laravel-uploadify),以便您可以在Eloquent模型字段上使用所有这些字段:

$car = Car::first();

$car->upload_cover_image->url();
$car->upload_cover_image->name();
$car->upload_cover_image->basename();
$car->upload_cover_image->extension();
$car->upload_cover_image->filesize();


2

存放方式:

public function upload($img){
   $filename = Carbon::now() . '-' .  $img->getClientOriginalName();
   return Storage::put($filename, File::get($img)) ? $filename : '';
}

路线:

 Route::get('image/{filename}', [
        'as'   => 'product.image',
        'uses' => 'ProductController@getImage',
    ]);

控制器:

 public function getImage($filename)
    {
        $file = Storage::get($filename);

        return new Response($file, 200);
    }

视图:

 <img src="{{ route('product.image', ['filename' => $yourImageName]) }}" alt="your image"/>

为什么有人要这样做,为什么要使用s3然后在Web服务器中将其代理化!
Shady Keshk '16

2

我发现的另一个解决方案是:

Storage::disk('documents')->getDriver()->getConfig()->get('url')

将返回带有文档存储路径的URL


1

看一下这个:如何使用storage_path()在laravel 4中查看图像。同样适用于Laravel 5:

存储用于文件系统,Web服务器无法访问其中的大部分。推荐的解决方案是将图像存储在公用文件夹(例如文档根目录)中的某个位置public/screenshots/。然后,要显示它们时,请使用asset('screenshots/1.jpg')


我试图在开发时将“磁盘”设置为我的公用文件夹,在实时环境
中将其设置为

没关系,Storage::path()返回服务器上文件的路径,但是您需要一个URL,并且Web服务器只能从文档根目录(即文件)提供文件<project>/public。在其中创建目录,然后使用url()asset()在刀片模板中。
nXu

2
Storage::path()不存在,但我想这么做
daviestar

好吧,我误会了,对不起。我要做的还是一样:保存数据库的完整路径,无论是本地还是s3。上传/创建图像时,只需检查getenv('debug')并确定要使用哪个图像。
nXu 2015年

我试图避免保存完整路径,但这也许是最明智的选择。
daviestar 2015年

1

就我而言,我为本地文件制作了单独的方法,在此文件中:src / Illuminate / Filesystem / FilesystemAdapter.php

    /**
 * Get the local path for the given filename.
 * @param $path
 * @return string
 */
public function localPath($path)
{
    $adapter = $this->driver->getAdapter();
    if ($adapter instanceof LocalAdapter) {
        return $adapter->getPathPrefix().$path;
    } else {
        throw new RuntimeException('This driver does not support retrieving local path');
    }
}

然后,我创建了对框架的拉取请求,但仍未合并到主核心中:https : //github.com/laravel/framework/pull/13605 可能是有人合并了这个)


0

这项工作将于2020年在Laravel 7为我完成

        $image_resize = Image::make($image->getRealPath());
        $image_resize->resize(800,600);
        $image_resize->save(Storage::disk('episodes')->path('') . $imgname);

所以你可以这样使用

echo Storage::disk('public')->path('');
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.