Laravel: load images stored outside 'public' folder
Solution 1
How about this (just tested it myself and it works):
The view:
<img src="/images/theImage.png">
Routes.php:
Route::get('images/{image}', function($image = null)
{
$path = storage_path().'/imageFolder/' . $image;
if (file_exists($path)) {
return Response::download($path);
}
});
Solution 2
Here is a slightly modified version of @Mattias answer. Assume the file is in the storage/app/avatars
folder which is outside the web root.
<img src="/avatars/3">
Route::get('/avatars/{userId}', function($image = null)
{
$path = storage_path().'/app/avatars/' . $image.'.jpg';
if (file_exists($path)) {
return response()->file($path);
}
});
Probably needs and else
. Also I have wrapped mine inside the middleware auth
Route Group which means you have to be logged in to see (my requirements) but I could do with more control over when it is made visible, perhaps alter the middleware.
EDIT Forgot to mention that this is for Laravel 5.3.
Solution 3
Here's what I came up with:
I'm trying to show the images in the view, not download. Here's what I came up with:
- Note that these images are stored above the public folder, which is why we have to take extra steps to display the image in the view.
The view
{{ HTML::image($user->getProfileImage(), '', array('height' => '50px')) }}
The model
/**
* Get profile image
*
*
*
* @return string
*/
public function getProfileImage()
{
if(!empty($this->profile_image) && File::exists($this->profile_image))
{
$subdomain = subdomain();
// Get the filename from the full path
$filename = basename($this->profile_image);
return 'images/image.php?id='.$subdomain.'&imageid='.$filename;
}
return 'images/missing.png';
}
public/images/image.php
<?php
$tenantId = $_GET["id"];
$imageId = $_GET["imageid"];
$path = __DIR__.'/../../app/storage/tenants/' . $tenantId . '/images/profile/' . $imageId;
// Prepare content headers
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path);
$length = filesize($path);
header ("content-type: $mime");
header ("content-length: $length");
// @TODO: Cache images generated from this php file
readfile($path);
exit;
?>
If somebody has a better way, please enlighten us!! I'm very interested.
kablamus
Updated on June 28, 2022Comments
-
kablamus almost 2 years
I'm trying to display an image stored outside the 'public' folder in my view. These are simple profile images whose paths are stored in the DB. The path looks like
/Users/myuser/Documents/Sites/myapp/app/storage/tenants/user2/images/52d645738fb9d-128-Profile (Color) copy.jpg
Since the image is stored a DB column for each user, my first thought was to create an Accessor in the User model to return the image. I tried:
public function getProfileImage() { if(!empty($this->profile_image)) { return readfile($this->profile_image); } return null; }
That produced unreadable characters in the view. I also tried file_get_contents() in place of read file. Any suggestions about how this might be accomplished?
-
martyn almost 9 yearsThis just returns the actual image src i.e. /images/theImage.png
-
Maximus over 5 yearsThis worked brilliantly. I wanted to show images outside of the webroot and this is exactly what I was looking for. So, thanks!