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

我把用户的头像上传到了Laravel存储器里。我如何访问它们并在视图中呈现它们?

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

402145 次浏览

最好的方法是创建一个符号链接,就像在答案如下中很好地指出的@SlateEntropy。为了帮助实现这一点,从5.3版开始,Laravel 包含一个命令使得这非常容易做到:

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

如果你正在使用干预图像库,你可以使用它内置的response方法使事情更简洁:

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

警告

请记住,通过人工服务,你会引起一个性能损失文件,因为你要经历整个Laravel请求生命周期才能读取和发送文件内容,这是相当慢而不是让HTTP服务器处理它。

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

例如

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

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

如果你是在windows上,你可以在cmd上运行这个命令:

mklink /j /path/to/laravel/public/avatars /path/to/laravel/storage/avatars
< p >: http://www.sevenforums.com/tutorials/278262-mklink-create-use-links-windows.html < / p >

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

storage/app/public

为了使它们可以从网络上访问,你应该创建一个从public/storagestorage/app/public的符号链接。

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

现在你可以在你的视图中使用资产助手创建一个指向文件的URL:

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

如果你正在使用php,那么请使用php符号链接函数,如下所示:

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

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

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

创建一个route/docs并指向任意控制器方法:

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

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

php artisan storage:link

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

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

如果你想加载少量的私人图像,你可以将图像编码到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;
我提到private是因为你应该只使用这些方法,如果你不想存储图像通过url公开访问,相反,你必须总是使用标准的方式 (链接存储/公用文件夹,并通过HTTP服务器提供图像).

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

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

如果你像我一样,你以某种方式拥有完整的文件路径(我在必需的照片上做了一些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 '';
}

无站点名称

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

如果你想添加站点名称 附加api JSON felids

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

如果磁盘“本地”不适合你,那么试试这个:

  1. 'default' => env('FILESYSTEM_DRIVER', 'public'),中的local从project_folder/config/filesystem.php更改为public
  2. 清除配置缓存php artisan config:clear
  3. 然后创建sym链接php artisan storage:link

要获取上传图像的url,可以使用Storage::url('image_name.jpg');

你可以在控制台中运行这个命令来创建链接:

php artisan storage:link

对我来说,它与子文件夹路由一起工作

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;
});