1

I need to be able to resize an image and put the resized version back into the $request, does anyone know if thats possible?

Basically I have inherited some code that contains potentially 100+ separate file upload sections, and it is now my task to resize all images on the site if they are above a certain size.

So I now need to intercept ALL image uploads on the application, detect if they are above a set size and if they are, resize them.

All code i've found online only shows how to resize the image then save the resized version straight away, but I need to be able to resize the image then put it BACK into the $request to be processed by the controller.

The images come in the form of arrays of images from separate sections, so i need to be able to loop the entire request, check if any of the inputs contain/are files, then if they are check the sizes of them. If they're above a set size, then resize them and replace them in the $request so that when the request continues, the controller can process the image as normal but it will be processing the new resized version.

I have tried resizing images and then using laravels $request->merge() method but I cannot get it to work.

At the moment I am resizing all images in a middleware, like this

public function handle($request, Closure $next)
{

    foreach($request->files as $fileKey => $file){

        //Create a new array to add the newly sized images in
        $newFileArray = [];


        //Get each of the files that are being uploaded in the request, if there are no files this will just be ignored.
        foreach ($file as $key => $f) {

            if(!is_null($f)){
                $image = Image::make($f);
                if($image->height() > 500 || $image->width() > 500){
                    $image->resize(500, null, function ($constraint) {
                        $constraint->aspectRatio();
                    });
                }
                $newFileArray[$key] = $image;
            } else {
                $newFileArray[$key] = null;
            }
        }

        $request->merge([
          $fileKey => $newFileArray
        ]);

    };

    return $next($request);
}

I just can't get it to work!

Is this possible?

EDIT

After a great suggestion in the comments of one of the answers below, I've achieved this by editing the temp image file directly so I don't have to mess with the request, this is how i've done it.

public function handle($request, Closure $next)
{

    foreach($request->files as $fileKey => $file){

        //Get each of the files that are being uploaded in the request, if there are no files this will just be ignored.
        foreach ($file as $key => $f) {
            if(!is_null($f)){
                $image = Image::make($f->getPathName());
                if($image->height() > 500 || $image->width() > 500){
                    $image->resize(500, null, function ($constraint) {
                        $constraint->aspectRatio();
                    });
                    $image->save($f->getPathName());
                }
            }
        }

    };

    return $next($request);
}
S_R
  • 1,818
  • 4
  • 27
  • 63
  • Why not resize the image in the controller? To be able to pass an image into another `$request` is to have the image stored somewhere before executing the `$request`. – Lars Mertens Oct 04 '18 at 14:17
  • 1
    @Lars probably because he's using a middleware architecture, where the request gets passed down a stack of request handlers – delboy1978uk Oct 04 '18 at 14:26

1 Answers1

1

I just read that Laravel uses PSR-7 requests.

https://laravel.com/docs/5.7/requests#psr7-requests

These are immutable. In other words, you can't change the data once set. What you can do however, is get it to create a new request with your new parameters.

Looking at the PSR-7 interface, we see there is a method which looks like exactly what you need:

https://github.com/php-fig/http-message/blob/master/src/ServerRequestInterface.php#L150

/**
 * Create a new instance with the specified uploaded files.
 *
 * This method MUST be implemented in such a way as to retain the
 * immutability of the message, and MUST return an instance that has the
 * updated body parameters.
 *
 * @param array $uploadedFiles An array tree of UploadedFileInterface instances.
 * @return static
 * @throws \InvalidArgumentException if an invalid structure is provided.
 */
public function withUploadedFiles(array $uploadedFiles);

So, do your thing, create your array, and once it's ready, replace your request like this:

$request = $request->withUploadedFiles($yourNewArray);
delboy1978uk
  • 12,118
  • 2
  • 21
  • 39
  • So how would you recommend I use this method with multidimensional arrays? As you can see in my example, the image arrays can always have different names – S_R Oct 04 '18 at 14:32
  • 1
    Well, I would assume that you can get the original array of `$_FILES`. Process your image, save it, and replace the paths in the original. ACTUALLY, having thought about it, why not just get the original array, load and resize, overwrite the original file in the temp storage folder, and don't even change the request? – delboy1978uk Oct 04 '18 at 14:41
  • 1
    Editing the temp folder was a stroke of genius! I'll add my new code to the question now, thanks! – S_R Oct 04 '18 at 15:03