3

I am having an issue with uploading an image in Laravel. Sometimes the image needs reorienting - when doing this with Intervention image it simply returns a boolean instead of the path of the image in s3. When using it without Intervention Image it works fine

I've tried exif reading data and using imagerotate to no avail, it errors out

I run the following

$image = $request->file('photo');
$path = \Storage::disk('s3')->put('users/'.\Auth::id().'/posts', $image, 'public');
dd($path); // /users/1/posts/39grjigrje.jpg

the $path variable is great and is the s3 path, however running:

$image = $request->file('photo');
$image = \Image::make($image);
$image->orientate();
$path = \Storage::disk('s3')->put('users/'.\Auth::id().'/posts', $image, 'public');
dd($path); // true

the $path variable is simply just a boolean and doesn't return the stored file path

I expect a path e.g. /images/1/kfjeieuge.jpg which I get when i don't use intervention image, when I use intervention I get a boolean.

iLC
  • 347
  • 9
  • 22

4 Answers4

3

I too had faced the same issue a few years back. I solved that by using following steps:

1.You may have to encode the image after an Intervention operation on it. To achieve encoding refer this documentation on stream method:Create encoded image stream

Encodes the current image in given format and given image quality and creates new PSR-7 stream based on image data.

$image = Image::make(request()->file('image'))->orientate()->encode('jpg');

2.And then storing it with a stream

$path = Storage::disk('s3')->put('users/'.\Auth::id().'/posts', $image->stream(),'public');

This should achieve your objective.

Nitesh
  • 77
  • 1
  • 7
2

In first example:

$image = $request->file('photo');
$path = \Storage::disk('s3')->put('users/'.\Auth::id().'/posts', $image, 
'public');

$request->file('photo') file will return instance of Illuminate\Http\UploadedFile class. you can check it here in documentation link.

And as Tarun said put method check for instance of Illuminate\Http\UploadedFile class. So in that case, it will uploaded successful.

In second example:

$image = $request->file('photo');
$image = \Image::make($image); //here
$image->orientate();
$path = \Storage::disk('s3')->put('users/' . \Auth::id() . '/posts', $image, 'public');

You are overwriting $image variable with instance Image class (second line). Which is wrong. You need to pass Stream or file.

Try below code:

$image = $request->file('photo');
$image = \Image::make($image); //here
$image->orientate()->encode('jpg');
$filename = time() . '.jpg';
$path = \Storage::disk('s3')->put('users/' . \Auth::id() . '/posts/'.$filename, $image->getEncoded(), 'public');
dns_nx
  • 3,651
  • 4
  • 37
  • 66
Dhaval Lad
  • 111
  • 3
0

You can solve it as described in the below link

https://laracasts.com/discuss/channels/laravel/saving-an-intervention-image-instance-into-amazon-s3

$path = \Storage::disk('s3')->put('users/'.\Auth::id().'/posts', $image->stream()->__toString(), 'public');

Update: 5 Jul

If you look at the source code it is supposed to return bool only

https://github.com/laravel/framework/blob/c7bdf66062af3c63648f7c29591476e6db92c885/src/Illuminate/Filesystem/FilesystemAdapter.php#L192

/**
     * Write the contents of a file.
     *
     * @param  string  $path
     * @param  string|resource  $contents
     * @param  mixed  $options
     * @return bool
     */
    public function put($path, $contents, $options = [])
    {
        $options = is_string($options)
                     ? ['visibility' => $options]
                     : (array) $options;
        // If the given contents is actually a file or uploaded file instance than we will
        // automatically store the file using a stream. This provides a convenient path
        // for the developer to store streams without managing them manually in code.
        if ($contents instanceof File ||
            $contents instanceof UploadedFile) {
            return $this->putFile($path, $contents, $options);
        }
        return is_resource($contents)
                ? $this->driver->putStream($path, $contents, $options)
                : $this->driver->put($path, $contents, $options);
    }

And as you can see a Stream and file is handled differently

And the ideal thing is to use url function to get the url

Storage::disk('s3')->url($filename)
Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265
  • this just returns true – iLC Jul 03 '19 at 05:02
  • @iLC yes, it does return true if all went well. But did it save the picture? Turan is right, you need to stringify the image in order to save an object on the S3. What do you see if you run `\Storage::allDirectories('users');` in tinker? If you see nothing, then there is something wrong with the IAM settings. – Dimitri Mostrey Jul 04 '19 at 08:22
0

Try this

$image = \Image::make($request->file('photo')->getRealpath());
$image->orientate();


$image->encode('jpg');
 OR
$image->response('jpg', 100);


$path = \Storage::disk('s3')->put('users/'.\Auth::id().'/posts', $image, 'public');
bhavinG
  • 19
  • 3