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.
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
How to Get the Byte Values of a String in PHP
How to Loop Through JSON Array
How to Iterate Through Dom Elements in PHP
How to Execute a Shell Script in PHP
Fetching One Row Only with MySQLi
Verify Valid Date Using PHP's Datetime Class
Accessing a Variable Defined in a Parent Function
Declaring a Global Variable Inside a Function
Prevent Session Expired in PHP Session for Inactive User
Compress/Archive Folder Using PHP Script
Set Character Set Using MySQLi
How to Install Imagemagick to Use with PHP on Windows 7 (3)
Laravel: General Error: 1615 Prepared Statement Needs to Be Re-Prepared