3

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)}}
Christophvh
  • 12,586
  • 7
  • 48
  • 70
  • I believe this is a file permission issue. Try setting the storage with a proper user privileged. – Nelson Melecio Feb 06 '17 at 07:25
  • the image is saved inside the storage folder, just nog resized. So it can write to the folder. I tried setting it to 777 but that also didn't solve the issue – Christophvh Feb 06 '17 at 08:08
  • I'm guessing that's because of the `$path` variable. Check it here: [Refence #1](http://stackoverflow.com/questions/33468437/getting-error-notreadableexception-in-abstractdecoder-php-line-302/33469360#33469360) or you might try what this guy did in [Reference #2](http://stackoverflow.com/questions/41990023/how-to-save-uploaded-image-to-storage-in-laravel). Best of luck. – Nelson Melecio Feb 06 '17 at 08:52
  • @Christophvh what is laravel version? The title contains `5.3`, but tags are with `5.4` in it – shukshin.ivan Feb 08 '17 at 17:35

2 Answers2

5

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.

shukshin.ivan
  • 11,075
  • 4
  • 53
  • 69
  • aha, that seems it! Gonna try it out tomorrow at work and will give you your bounty. But that finally makes sense. – Christophvh Feb 08 '17 at 18:50
1

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.

CUGreen
  • 3,066
  • 2
  • 13
  • 22
  • That makes sense, but didn't solve the issue, got the same 'Image not readable error' , but now referring to this path: `home/vagrant/php-resq/storage/clients/logos/ObaIpvgexGPcOStz0jaU73BJ8AUDp2ME85lUpMoY.jpeg` again the 'app' is not showing in that path – Christophvh Feb 06 '17 at 12:20
  • Then you just need to prepend ```app/``` to your path and that should work. The reason you are getting ```Image not readable``` is because you are not providing the correct path. – CUGreen Feb 06 '17 at 22:14
  • Adding app, seems like a hacky solution, so not really gonna do that. Got it working without using canvas() gonna ad that to my first post, so maybe someone will find a solution based on that – Christophvh Feb 07 '17 at 08:23