ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

“+1”谢谢。也许本教程更有帮助:How to display the storage folder image in Laravel?

C
Community

最佳 方法是创建一个符号链接,如the answer below 中很好指出的@SlateEntropy。为了帮助解决这个问题,从 5.3 版开始,Laravel includes a command 让这变得非常容易:

php artisan storage:link

这将为您创建一个从 public/storagestorage/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

如果您使用 Intervention Image Library,您可以使用其内置的 response 方法使事情更简洁:

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

警告请记住,通过手动提供文件会导致性能损失,因为您要经历整个 Laravel 请求生命周期才能读取和发送文件内容,这比让 HTTP 服务器处理它要慢得多.


这似乎很好。我想再问一个问题。是否建议将头像、拇指等文件(用户上传的文件)存储在存储中?
您可以将它们存储在您喜欢的任何位置,但除非这些是私有文件,否则我认为您最好将它们存储在 public 目录中。这样,您将避免编写图像响应的开销,该响应可以由 HTTP 服务器更快地处理。
就个人而言,我不会将用户文件存储在公用文件夹中,当存储文件夹用于存储时,我发现事情更加整洁和易于管理。
我不会推荐其中任何一个,因为那样你会增加再次加载 Laravel 和/或利用 PHP 读取每个图像的开销。使用 CmdSft 描述的符号链接会快得多。
@user1960364 这就是最后一段强烈建议使用符号链接方法的原因。但答案本身,虽然从性能的角度来看不是最佳解决方案,但仍然有效,并且可能是人们在可能无法设置符号链接的共享服务器上运行应用程序的唯一方法。答案还展示了如何在需要时以编程方式提供文件,可能是为了提供像 this question 中所要求的加密文件。
S
SlateEntropy

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

例如

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

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


我对此有点陌生。这需要在终端上运行还是在 laravel 的某个配置文件中定义?
是的,您需要通过命令行运行它。它需要在您部署应用程序的任何地方进行设置。
对于 Windows 用户,如果您不想使用 CMD,这里有一个独立的工具:github.com/amd989/Symlinker#downloads
该问题询问如何公开显示存储在 storage 中的用户头像,通常头像不需要任何类型的访问控制。如果不需要任何安全性,则使用任何类型的中间件或路由只会浪费您的资源。值得注意的是,从 Laravel 5.2 开始,使用符号链接的公共文件 (laravel.com/docs/5.2/filesystem) 存在一个单独的文件“磁盘”。
在 Laravel 5.3 中有一个 artisan 命令可以做到这一点:$ php artisan storage:link
P
Piotr

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

storage/app/public

要使它们可以从 Web 访问,您应该创建一个从 public/storagestorage/app/public 的符号链接。

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

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

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

c
cabs

如果您在 Windows 上,您可以在 cmd 上运行此命令:

mklink /j /path/to/laravel/public/avatars /path/to/laravel/storage/avatars 

来自:http://www.sevenforums.com/tutorials/278262-mklink-create-use-links-windows.html


H
Haider Ali

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

php artisan storage:link

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

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

B
Barry

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

创建一个路由/文档并指向任何控制器方法:

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 上测试的。


B
Barry

如果您想加载少量 Private 图像,您可以将图像编码为 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() 有两个重要的缺点:

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


D
Dnyaneshwar Harer

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

在 'default' => env('FILESYSTEM_DRIVER', 'public') 中将本地更改为公共,从 project_folder/config/filesystem.php 清除配置缓存 php artisan config:clear 然后创建 sym 链接 php artisan storage:link

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


完美,谢谢!
J
Jehad Ahmad Jaghoub

没有站点名称

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

如果您想将站点名称添加到它的示例以附加到 api JSON felids

 public function getPhotoFullLinkAttribute()
{
 Storage::url($this->attributes['avatar']) ;
}

M
Mubashar Iqbal

如果您使用的是 php,那么请使用 php 符号链接功能,如下所示:

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

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


这个具体用在哪里?
ssh 终端,如果您有 ssh 访问权限
m
miken32

您可以在控制台中运行此命令以建立链接:

php artisan storage:link

D
Damilola Olowookere

如果您像我一样拥有完整的文件路径(我对所需的照片进行了一些 glob() 模式匹配,所以我最终得到了完整的文件路径),并且您的存储设置链接得很好 (即你的路径有字符串 storage/app/public/),那么你可以使用我下面的小脏 hack :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 '';
    }

Y
Yogesh.galav

对我来说,它与子文件夹路线一起使用

Route::get('/storage/{folder}/{filename}', function ($folder,$filename)
{
    $path = storage_path('app/public/' .$folder.'/'. $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;
});