How to Serve an Image with Laravel

How should I serve an image with Laravel?

The Short Answer to your Question

Can this be considered a good practice, or should I simply save
pictures in the public folder? Will I run into performance issues by
doing so?

It is not suggested practice, because you read the file and re-generate it, that will take process time and load the server, but that said all depends on how many requests, image size, etc. I used this practice to secure/protect images/files from public access, so only Authenticated member can access the images/files as it is in this answer. Again depending on file size, number of requests and server specification, I have used it for while and I have had no issues with performance, it has worked fine (my server is 512MBMemory, 1 CoreProcessor, 20GBSSD Disk VPS solution). You might give it a try for while and see.

Symbolic link solution

It is also possible, to create symbolic link like

ln -s /pathof/laravel/storage/profile_pictures /pathof/laravel/public/profile

This solution won't affect performance, but you need to document the solution in your internal documentation, in case you move your setup to new provider or in case you need to re-link to the storage folder.

But if you still wish to have the full solution for returning image from storage folder, first of all we need to install Intervention Image for Laravel, I am not sure if this done already or not. if you have install it continue here, but if not follow the last part of this answer and than continue with Laravel solution.

Laravel solution

As said we assume your intervention works, first of all you need to create a Route. The Route will forward all image request access to our Controller.

Create Route

Route::get('profile/{person}', 'ImagesController@profilePicture');

After creating a route, we need to create a controller to take care of image requests from our route.

Create ImagesController

From command

php artisan make:controller ImagesController

And your controller should look like this.

class ImagesController extends Controller {

public function profilePicture($person, $size = 40)
{
$storagePath = storage_path('/profile_pictures/' . $person . '/profile_' . $size . '.jpg');

return Image::make($storagePath)->response();
}
}


EDIT

For those who use Laravel 5.2 and newer. Laravel introduces new and better way to serve files that has less overhead (This way does not regenerate the file as mentioned in the answer):

File Responses

The file method can be used to display a file, such as an image or
PDF, directly in the user's browser instead of initiating a download.
This method accepts the path to the file as its first argument and an
array of headers as its second argument:

return response()->file($pathToFile);

return response()->file($pathToFile, $headers);

And remember to add

use Intervention\Image\Facades\Image;

in your ImagesController class

Finally be sure you have created folder structure with test image.

storage/profile_pictures/person/profile_40.jpg

Now if you write in your browser

http://laravelLocalhostUrl/profile/person

It will show your image, I have made it my self and test it.
Sample Image

Note: I have tried best possible to make folder reflect your question,
but you can easily modify it to fit the way you want.


Install Intervention (skip this part if you already installed it)

Follow this guideline for it: http://image.intervention.io/getting_started/installation

Briefly: php composer require intervention/image

And In in your config/app the $providers array add the service providers for this package.

Intervention\Image\ImageServiceProvider::class

Add the facade of this package to the $aliases array.

'Image' => Intervention\Image\Facades\Image::class

The solution inspired from this answer but that one is to protect image with authentication in general and this answer.

Return Response Image in Laravel 7

This is not working just because of the returning image source <img src="/assets/fe/img/welcome.jpeg" alt="Smiley face" width="200"> is not available on your JSFiddle, even it will not work on any other website because no one have the image on this relative path /assets/fe/img/welcome.jpeg. If you want to really do that you have to specify the full absolute path. <img src="https://www.bunlongheng.com/assets/fe/img/welcome.jpeg" alt="Smiley face" width="200">.

So your return statement could be.

return '<img src="env('APP_URL')/assets/fe/img/welcome.jpeg" alt="Smiley face" width="200">';

Or whatever you think is good to specify the absolute path.

Further Explanation

I have checked on the JSFiddle source code, you are using this link https://www.bunlongheng.com/img/UoJb9wl.png in the image src tag. It will not work at all if you even specify the absolute path.

<img src="https://www.bunlongheng.com/img/UoJb9wl.png">

When browser will try to populate the src tag it will send request to https://www.bunlongheng.com/img/UoJb9wl.png and the response code is <img src="/assets/fe/img/welcome.jpeg" alt="Smiley face" width="200"> so browser will populate it like this.

<img src="<img src="/assets/fe/img/welcome.jpeg" alt="Smiley face" width="200">">

So you have to return only the image path in the request, if you want to use this route in the image's src.

return env('APP_URL')."/assets/fe/img/welcome.jpeg"

If you want to keep your return statement same with image tag, then you can't use that route in image's src. Just use in the div or any other html tag.

How to serve scaled images in Laravel?

This means you must have an image in your server the size of the container you're viewing it in, for example an image on mobile should have a maximum width of 425px

If the images are static, you could create each image for the container width it is showing in the pageSpeed report.

Otherwise you could use a package like intervention, this package lets you manipulate images as you want, but this means more process on the server side.

Serving PHP image resource as response in Laravel

Finally, I have got the solution based on some answers. I just needed to return like this.

return response(Storage::disk('s3')->get($request->get('identifier')))->header('Content-Type', 'image/png');

In the response, I passed image data, not the file path. Then I set the content type in the header. Thanks eveyone.

View uploaded image in a laravel blade which is running on a php artisan serve server

when you call storage path use storage_path LINK

<img src="{{ storage_path('uploads/profile/'.$data->profile_picture) }}>

or you can use laravel storage:link LINK
run this command it will create virtual directory in your public folder
so you can use like below

php artisan storage:link

<img src="{{ asset('uploads/profile/'.$data->profile_picture) }}>

or using Storage::url()

<img src="{{ Storage::url('/storage/uploads/profile/'.$data->profile_picture) }}" alt="{{ $images->filename }}" />

How can I solve an image add issue on Laravel 8?

Check your storage folder permissions

if you are on localhost try 777

if you are on server you can try 755

Create symbolic link

php artisan storage:link

Specify a public disk, example

$path = $request->file('file')->store(
'offer_images/'.$request->user()->id, 'public'
);

Retrieve file

$url = Storage::url('file.jpg');

Since you are getting 404 Not Found try retrieving file with domain

$url = env('APP_URL').Storage::url('file.jpg');


Related Topics



Leave a reply



Submit