0

I'm trying to create multiple copies of profile pic in different sizes when a profile is created. But I am constantly getting this error:

" NotReadableException: Image source not readable"

Can somebody point me what I'm missing in my below code:

public function updateprofile(UserProfileRequest $request){
    $user_id = Auth::User()->id;
    $profile = UserProfile::where('user_id','=',$user_id)->first();
    $profile->fullname = $request->fullname;

    if ($request->hasFile('img')) {
        if($request->file('img')->isValid()) {
            $types = array('_original.', '_32.', '_64.', '_128.');
            $sizes = array( '32', '64', '128');
            $targetPath = 'public/uploads/'.$user_id;

            try {
                $file = $request->file('img');
                $ext = $file->getClientOriginalExtension();
                $fName = time();
                $original = $fName . array_shift($types) . $ext;
                Storage::putFileAs($targetPath, $file, $original);

                foreach ($types as $key => $type) {
                    $newName = $fName . $type . $ext;
                    Storage::copy($targetPath . $original, $targetPath . $newName);
                    $newImg = Image::make($targetPath . $newName);
                    $newImg->resize($sizes[$key], null, function($constraint){
                        $constraint->aspectRatio();
                    });
                    $newImg->save($targetPath . $newName);
                }

                $profile->img = 'public/uploads/'.$user_id;
            } catch (Illuminate\Filesystem\FileNotFoundException $e) {
            }
        }
    }

    $profile->save();}
4
  • Can you post the form in your view that is submitting this request? Commented Nov 21, 2017 at 15:09
  • Here is the image upload field in the view page: <label for="img" class="col-md-2 control-label"> Photo</label> <div class="col-md-4 inputContainer"> <div class="input-group"> {!! Form::file('img',null,array( 'id'=>'img' )) !!} {!! $errors->first('img') !!} </div> </div> Please let me know if you need anything else. Commented Nov 21, 2017 at 15:32
  • 1
    do you use 'files' => 'true', 'enctype' => "multipart/form-data" in your form? Commented Nov 21, 2017 at 15:52
  • Yes, I have used them: {!! Form::model($profile, ['route'=>'profile','method'=>'post', 'files'=>'true', 'enctype'=>'multipart/form-data']) !!} {!! csrf_field() !!} Commented Nov 21, 2017 at 15:58

3 Answers 3

1

I had the same issue i ran this command and it worked

php artisan storage:link

This command creates a storage directory under the public folder.

Also use public path function to get the public path

$targetPath = public_path('storage/uploads/'. $user_id);

The 'storage' used inside the laravel public_path() function is used to get the storage main folder.

Sign up to request clarification or add additional context in comments.

Comments

0

If I'm not mistaken, the path which is provided should be the absolute filepath on your server. For example instead of:

$targetPath = 'public/uploads/'.$user_id;

Use (your actual path will vary depending on your configuration)

$targetPath = '/var/www/sitename/public/uploads/'.$user_id;

Laravel also contains a helper function called public_path() which can be used to obtain the "fully qualified path to the public directory". This would allow you to use something such as:

$targetPath = public_path('uploads/'. $user_id);

Also, on this line, do not forget to place a slash before the new filename:

$newImg = Image::make($targetPath . '/' . $newName);

I would also confirm that the user executing the script (if apache or nginx usually www-data unless altered) has write permissions to your public/uploads/ directory

Comments

0

Finally, I got it working. I made following changes to my code:

  1. Use the full OS path as suggested by commanderZiltoid for the destination path.
  2. Don't use Storage::putFileAs method to save the file. So, remove this line: Storage::putFileAs($targetPath, $file, $original);
  3. Don't use Storage::copy() to copy the file, so, remove this line: Storage::copy($targetPath . $original, $targetPath . $newName);
  4. For points 2 and 3, use Image::make($file->getRealPath()); This will create the file and remember the path where the file was created. Image->resize method will use this path later.
  5. In the end, save the relative path in the database, as here: $profile->img = 'storage/uploads/'.$user_id.'/img/profile/'.$fName. Since we'll use {{ asset($profile->img) }}, it's necessary to save only the relative path and not the absolute OS path.

    if($request->hasFile('img')) {
    
        if($request->file('img')->isValid()) {
    
            $types = array('_original.', '_32.', '_64.', '_128.'); 
    
            $sizes = array( array('32','32'), array('64','64'), array('128','128'));
            $targetPath = '/Users/apple/Documents/_chayyo/chayyo/storage/app/public/uploads/'.$user_id.'/img/profile/';
    
        try {
            $file = $request->file('img');
            $ext = $file->getClientOriginalExtension();
            $fName = time();
            $o_name = $fName . array_shift($types) . $ext;
            $original = Image::make($file->getRealPath());
            $original->save($targetPath . $o_name);
    
            foreach ($types as $key => $type) {
                $newName = $fName . $type . $ext;
                $newImg = Image::make($file->getRealPath());
                $newImg->resize($sizes[$key][0], $sizes[$key][1]);
                $newImg->save($targetPath . $newName);
            }
    
            $profile->img = 'storage/uploads/'.$user_id.'/img/profile/'.$fName;
    
        } 
         catch (Illuminate\Filesystem\FileNotFoundException $e) {
    
        }
      }
    }
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.