问题
Running Laraval 5.4 with Vagrant and Homestead.
Saw a few other questions regarding this issue but none provided a solution which uses the canvas() method by Intervention/Image
Laravel introduced a easier storage system since 5.3
My current code:
$path = $request->file('logo')->store('/clients/logos','public');
$canvas = Image::canvas($width, $height);
$image = Image::make($path)->resize($width, $height, function ($constraint)
{
$constraint->aspectRatio();
});
$canvas->insert($image, 'center');
$canvas->save($path);
$this->logo_path = $path;
This code creates a canvas and places a resized image inside it.
This code gives following error:
NotReadableException in AbstractDecoder.php line 335: Image source not readable in AbstractDecoder.php line 335 at AbstractDecoder->init('clients/logos/UupUn1iuDGRsy5Z0bkWHJ6S4v79bfZiXapTO7vLk.jpeg') in AbstractDriver.php line 64
The first line works, because the image is stored inside my storage folder at the following location:
"/storage/app/public/clients/logo/UupUn1iuDGRsy5Z0bkWHJ6S4v79bfZiXapTO7vLk.jpeg"
but the image is stored in full-size, so the code fails at the image-intervention part.
Things i tried:
I tried changing the $path
variable inside Image::make() to this:
Storage::disk('public')->url($path)
which results in following error: Can't write image data to path
(http://test.dev/storage/clients/logos/owjNA5Fn9QyYoS0i84UgysaFLo5v0NzbOiBhBzXp.jpeg)
The weird part about that error is that the 'app' directory is not visible inside that error.
I'm running out of ideas to solve this issue.
Edit
Got it working without using canvas, but still would like to know a way to use canvas()
This is how i currently got it working:
$path = $logo->hashName('public/clients/logos');
$image = Image::make($logo);
$image->resize($width, $height, function ($constraint)
{
$constraint->aspectRatio();
});
Storage::put($path, (string) $image->encode(), 'public');
$this->logo_path = $path;
Retrieving the image
{{Storage::url($client->logo_path)}}
回答1:
My first thought was that you have a typo - code contains both logo
and logos
paths.
Then I installed laravel with canvas and got the same error. So I've just made a little path improvements and now it works. The key point is that the returned $path is relative not to your storage path but to storage/app/public.
$width = 50;
$height = 50;
// here $path is set to "clients/logos/FWGXEf9AJ0NOspFoxelTtGUqmr0YP4ztUMUcqkXc.png"
$path = $request->file('logo')->store('/clients/logos','public');
// creating a canvas
$canvas = Image::canvas($width, $height);
// pass the right full path to the file. Remember that $path is a path inside app/public !
$image = Image::make(storage_path("app/public/" . $path))->resize($width, $height,
function ($constraint) {
$constraint->aspectRatio();
});
$canvas->insert($image, 'center');
// pass the full path. Canvas overwrites initial image with a logo
$canvas->save(storage_path("app/public/" . $path . ".png"));
Canvas needs full paths or chdir() to it, it can be easy checked in e.g. Intervention\Image\Image
source file (./vendor/intervention/image/src/Intervention/Image/Image.php
).
The save
method contains simple $saved = @file_put_contents($path, $data);
and no any chdir
call.
回答2:
With your code:
$path = $request->file('logo')->store('/clients/logos','public');
the returned $path
is relative to your storage path.
You need to provide a fully qualified path to the public storage directory.
This can be achieved by using the helper function storage_path() so you use storage_path($path)
instead of just $path
Therefore your code should look like this:
$path = $request->file('logo')->store('/clients/logos','public');
$canvas = Image::canvas($width, $height);
$image = Image::make(storage_path('app/'.$path))->resize($width, $height, function ($constraint)
{
$constraint->aspectRatio();
});
$canvas->insert($image, 'center');
$canvas->save(storage_path('app/'.$path));
$this->logo_path = 'app/'.$path;
It is worth mentioning that this has not been tested but I would assume this is your issue.
Edit: Also, when using Storage::disk('public')->url($path)
, it is going to return a storage/
path relative to your public directory. Therefore, as the docs mention:
The
storage/app/public
directory may be used to store user-generated files, such as profile avatars, that should be publicly accessible. You should create a symbolic link atpublic/storage
which points to this directory. You may create the link using thephp artisan storage:link
command.
Might help you down the track when you want to serve up that image in your view.
来源:https://stackoverflow.com/questions/42032644/use-laravel-storage-with-image-intervention-canvas