sarathiscookie's avatar

Laravel 5 - How can we access image from storage

I need to view profile pic when page loads. I have used laravel storage for upload image but I don't know how to retrieve and view image. Please check my below code and help me.

Current image folder is storage/app/1/1.jpeg

Laravel Code

public function index()
{
        $id = Input::get('id');
        User::findOrFail($id);
        $file = Storage::get($id.'/'.$id.'.'.'jpeg'); 
        return response($file, 200)->header('Content-Type', 'image/jpeg');
}

JS

<script>
    $(function(){
        $.post("/viewProfile/image", { id: 1 })
                .done(function( data ) {
                    $('#responseImage').html('<img src="'+data+'">');
        });
    })
</script>

routes

Route::post('/viewProfile/image',[
    'before'  => 'csrf',
    'as'      => 'viewprofileimage',
    'uses'    => 'ProfileimageController@index']);

HTML

<div id="responseImage"> </div>
0 likes
18 replies
Snapey's avatar

Blimey... where to begin?

In the controller you are trying to return just the filepath? That is a text string, not an image/jpg

If you just hit that route in your browser, do you get the image path in return? Use Postman (https://www.getpostman.com/) if you need to generate a post request (but most would just code Route::get(/viewProfile/image/{id}) )

(infact what you should do is obfuscate the path so that someone cannot just crawl all the profile images - see https://philsturgeon.uk/http/2015/09/03/auto-incrementing-to-destruction/ )

You would use the content type header if you were actually streaming the image in the response.

Is this like a single page app where you are trying to get all the assets client side? Are you using some framework?

sarathiscookie's avatar

@Snapey , My firebug console shows response. Some encoded data like "�����JFIF�,,�����C�" and status is 200 OK 190ms

Snapey's avatar

forget firebug... what do you expect returned? An image or the path to an image?

Snapey's avatar

sorry for all the questions. Clever people here might fix your code, but that does not necessarily mean it is the right code.

there are many ways to achieve the same thing so when someone seems to be doing it a difficult way, the question has to be why? what sort of problem are you trying to solve?

Why in this bit of code do you need to retrieve the image when you did not think you needed to when you first sent the view to the user?

sarathiscookie's avatar

@Snapey, I will explain. It is a user profile page. When user login to the system they can view their profile page. Eg user id is 1. In my code I am trying to pass this user id "1" to controller page and getting image of particular user. User images are stored under storage/app/1/1.jpeg. i think it reads you will get an overall idea.

Snapey's avatar

OK, so why don't you just pass the url to the image with the view.

To help, in your UserController create a function;

    public function getProfileImage(){

    return Storage::get($this->id.'/'.$this->id.'.jpeg');
    }

Then in your view, just do

name: { { $user->name } }
email: { { $user->email } }

photo: <img src="{ { $user->getProfileImage } }" />

(note that I have had to double space the braces for the forum only)

martinbean's avatar

@sarathiscookie Store the profile picture filename in your users database table in a column called avatar_filename or similar. Then move the actual image file to a web-accessible directory when the user uploads it, somewhere like public/img/avatars.

When you fetch a user, you’ll get the filename. So if I upload a file called example.jpg, then the path would be public/img/avatars/example.jpg. So in your view, you can do this:

<img src="{{ asset('img/avatars/'.$user->avatar_filename) }}" alt="Avatar" />

You’ll also need to make sure filenames don’t clash, i.e. if two users upload profile images with the same filename. Personally, I use the uniqid() PHP function and use that as filenames of uploaded images. In the case of profile pictures, there’s no reason why you couldn’t name them by a hash of the user’s primary key (i.e. sha1($user->getKey())). This means you won’t be exposing your users’ IDs via filenames.

1 like
sarathiscookie's avatar

@Snapey , My controller page is ProfileimageController.php. I have created function like you mentioned. How can i get in <img tag?

Snapey's avatar

Sorry, I should have said create that function in your User model

balasubramani's avatar

Hi, I am also face the same problem. Storage::get does not return the file path. it return content. if content came how to handle image, PDF, etc...

Controller

$path=Storage::get('pdf/a.jpg');
return view('test.view', compact('path'));

View

<img src="{{ $path }}" >
Snapey's avatar

@balasubramani storage is not public. You cannot save files there then create web links to them. This thread is about being able to use laravel to intercept the call for the image, get it from private storage and stream the file to the client.

Start your own thread with what you are trying to do and what you have done so far.

1 like
balasubramani's avatar

@Snapey

Thanks for guide.

I want to secure each file. So only I choose storage location. way of getting file's content throw streaming.

Is this proper way for programming.

Controller

$path=Storage::get('pdf/pdf.pdf');

View File

<embed width="100%" height="100%" src="data:application/pdf;base64,{{ base64_encode($path) }}">

Thanks for reply.

maikealame's avatar

I do this:

Route::get('/image/{path}/{file}', ['as'=>'image', 'uses'=>'ImageController@getImage']);
public function getImage($path,$file){
        if($file){
            $url = $path."/".$file;
        }else{
            $url = $path;
        }
        $path = storage_path("app/") . $url;

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

Now, I can use my ACL for this route or other condition rules inside controller.

Please or to participate in this conversation.