3

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?

2
  • this stackoverflow.com/questions/5630266/a-php-file-as-img-src seems to cover this pretty nicely. Commented Jan 15, 2014 at 11:31
  • Thanks. That helped. I had read it -- but didn't understand it until I reread it. Posted an answer below. Commented Jan 15, 2014 at 19:24

3 Answers 3

6

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);
    }
});
Sign up to request clarification or add additional context in comments.

2 Comments

This just returns the actual image src i.e. /images/theImage.png
This worked brilliantly. I wanted to show images outside of the webroot and this is exactly what I was looking for. So, thanks!
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.

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.