Laravel 5-如何访问View中存储中上传的图像?


171

我已经将用户的头像上传到Laravel存储中。如何访问它们并在视图中呈现它们?

服务器将所有请求都指向/public,因此如果它们在/storage文件夹中,该如何显示它们?

Answers:


349

最好的方法是创建一个符号链接像@SlateEntropy相当不错,指出了下面的答案。为了解决这个问题,从5.3版开始,Laravel 包含了一个使此操作非常容易的命令

php artisan storage:link

这会为您创建从public/storage到的符号链接,storage/app/public仅此而已。现在/storage/app/public可以通过以下链接访问其中的任何文件:

http://somedomain.com/storage/image.jpg

如果由于某种原因而无法创建符号链接(例如,您正在共享主机上等),或者想要保护某些访问控制逻辑后面的文件,则可以选择使用特殊的路由来读取和读取提供图像。例如,如下所示的简单关闭路线:

Route::get('storage/{filename}', function ($filename)
{
    $path = storage_path('public/' . $filename);

    if (!File::exists($path)) {
        abort(404);
    }

    $file = File::get($path);
    $type = File::mimeType($path);

    $response = Response::make($file, 200);
    $response->header("Content-Type", $type);

    return $response;
});

现在,您可以像使用符号链接一样访问文件:

http://somedomain.com/storage/image.jpg

如果您使用的是干预图像库,则可以使用其内置response方法使事情更简洁:

Route::get('storage/{filename}', function ($filename)
{
    return Image::make(storage_path('public/' . $filename))->response();
});

警告

请记住,手动提供文件会导致性能下降,因为您要经历整个Laravel请求生命周期才能读取和发送文件内容,这比HTTP服务器处理文件的速度要慢得多。


好像很好 我想再问一个问题。是否建议将化身,拇指等文件(用户上传的文件)存储在存储中?
TadeášJílek

5
您可以将它们存储在任意位置,但是除非这些文件是私有文件,否则我认为最好将它们存储在public目录中。这样,您将避免必须组成图像响应的开销,该响应可以由HTTP服务器更快地处理。
博格丹2015年

2
就个人而言,我不会将用户文件存储在公用文件夹中,当使用存储文件夹进行存储时,我发现事情变得更整洁和更易于管理。
SlateEntropy

2
我不推荐使用这两种方法,因为那样会增加再次加载Laravel和/或利用PHP读取每个图像的开销。使用CmdSft描述的符号链接会更快。
user1960364 '16

4
@ user1960364这就是为什么最后一段强烈建议使用符号链接方法的原因。但是,从性能的角度来看,答案本身虽然不是最佳的解决方案,但它仍然是有效的,并且对于在无法建立符号链接的共享服务器上运行应用程序的人们而言,答案可能是唯一的方法。答案还展示了如何在需要时以编程方式提供文件服务,也许可以提供本问题中要求的加密文件。
Bogdan

53

一种选择是在存储目录和公共目录的子文件夹之间创建符号链接。

例如

ln -s /path/to/laravel/storage/avatars /path/to/laravel/public/avatars

这也是Envoyer使用的方法,Envoyer是Laravel的开发者Taylor Otwell构建的部署管理器。


我对此有些陌生。这是否需要在终端上运行或在laravel中的某个配置文件中定义?
Gaurav Mehta

是的,您需要通过命令行来运行它。需要在部署应用程序的任何地方进行设置。
SlateEntropy

对于Windows用户,如果您不想使用CMD,可以使用以下独立工具:github.com/amd989/Symlinker#downloads
David

3
该问题询问如何显示storage公开存储的用户头像,通常头像不需要任何类型的访问控制。如果不需要使用任何中间件或路由的安全性,那只会浪费您的资源。还值得注意的是,由于Laravel 5.2 使用符号链接为公共文件(laravel.com/docs/5.2/filesystem)提供了一个单独的文件“磁盘” 。
SlateEntropy

6
在Laravel 5.3中有一个工匠命令来执行此操作:$ php artisan storage:link
Phil

22

根据Laravel 5.2文档,您的公共可访问文件应放在目录中

storage/app/public

为了使它们可以从Web上访问,您应该创建从public/storage到的符号链接storage/app/public

ln -s /path/to/laravel/storage/app/public /path/to/laravel/public/storage

现在,您可以使用资产助手在视图中创建文件的URL:

echo asset('storage/file.txt');


13

首先,您需要使用artisan命令为存储目录创建符号链接

php artisan storage:link

然后,在任何视图中,您都可以像这样通过url帮助器访问图像。

url('storage/avatars/image.png');

4

最好将所有私有图像和文档保存在存储目录中,然后您将完全控制文件以太,您可以允许某些类型的用户访问文件或进行限制。

制作路径/文档并指向任何控制器方法:

public function docs() {

    //custom logic

    //check if user is logged in or user have permission to download this file etc

    return response()->download(
        storage_path('app/users/documents/4YPa0bl0L01ey2jO2CTVzlfuBcrNyHE2TV8xakPk.png'), 
        'filename.png',
        ['Content-Type' => 'image/png']
    );
}

当您命中时,localhost:8000/docs将下载文件(如果存在)。

该文件必须root/storage/app/users/documents根据上述代码位于目录中,已在上进行了测试Laravel 5.4


4

如果要加载少量的私有映像,则可以将映像编码为base64并<img src="{{$image_data}}">直接将它们回显到:

$path = image.png
$full_path = Storage::path($path);
$base64 = base64_encode(Storage::get($path));
$image_data = 'data:'.mime_content_type($full_path) . ';base64,' . $base64;

我提到私有的是因为您只应在不想存储可通过url公开访问的图像时使用这些方法,而必须始终使用标准方式(链接存储/公共文件夹并通过HTTP服务器提供图像)。

当心编码base64()有两个重要的缺点:

  1. 这将使图像尺寸增加约30%。
  2. 您可以将所有图像大小合并到一个请求中,而不是并行加载它们,这对于一些小的缩略图应该不是问题,但是对于许多图像,避免使用此方法。

2

如果您使用的是php,则请使用php symlink函数,如下所示:

symlink('/home/username/projectname/storage/app/public', '/home/username/public_html/storage')

将用户名和项目名称更改为正确的名称。


1

没有网站名称

{{Storage::url($photoLink)}}

如果要向其添加站点名称示例以附加在api JSON felids上

 public function getPhotoFullLinkAttribute()
{
    return env('APP_URL', false).Storage::url($this->attributes['avatar']) ;
}

0

如果您像我一样,并且以某种方式拥有完整的文件路径(我对所需照片进行了glob()模式匹配,那么我最终会得到完整的文件路径),并且您的存储设置已很好地链接了(例如,您的路径有字符串storage/app/public/),那么您可以使用下面的我的小技巧:p)

 public static function hackoutFileFromStorageFolder($fullfilePath) {
        if (strpos($fullfilePath, 'storage/app/public/')) {
           $fileParts = explode('storage/app/public/', $fullfilePath);
           if( count($fileParts) > 1){
               return $fileParts[1];
           }
        }

        return '';
    }

0

如果磁盘“ local”不适合您,请尝试以下操作:

  1. 更改本地市民'default' => env('FILESYSTEM_DRIVER', 'public'),project_folder/config/filesystem.php
  2. 清除配置缓存 php artisan config:clear
  3. 然后创建符号链接 php artisan storage:link

要获取上传图片的网址,您可以使用此网址 Storage::url('iamge_name.jpg');

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.