Use laravel storage with Image intervention canvas()

夙愿已清 提交于 2020-01-04 01:19:20

问题


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 at public/storage which points to this directory. You may create the link using the php 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!