How to Upload and Compress Images in Laravel

Are you looking for how to upload and compress images in Laravel? Laravel provides an easy way for file uploading. And compressing the images at the time of uploading is a good practice. In this article, I show you how to upload and compress images in Laravel.

Why Need to Compress Images?

Images play an important role in your website. Images add better UX and eye-catching experience for the visitors. But at the same time, it can also kill the site performance. Heavy images slow down the site. As a result, your site takes a long time to load. Users don’t like slow websites. If your site takes more time to load, it is a high chance you lose your audiences. The standard loading time for a website is 2 seconds. You should take care that your site is loading within 2 seconds.

Though there are several factors that need to be taken into consideration in order to improve the page speed, one of them is the use of optimized images. Compressing images reduces the size of your original image without losing its quality. It helps to increase site speed.

Having said that, let’s see how to upload and compress images in Laravel.

Uploading Images in Laravel

Laravel provides a clean way to upload the images. For getting started with it, we first need to create a directory where we will store the images. Open your command prompt in the root directory and run the below command.

php artisan storage:link

This command creates a ‘storage’ directory under the ‘public’ folder.

Next, create a form with the file input and submit button by adding the below code in your blade file.

<form action="{{ url('ROUTE_HERE') }}" method="post" enctype="multipart/form-data">
    <div class="form-group">
        <label for="exampleInputFile">File input</label>
        <input type="file" name="profile_image" id="exampleInputFile">
    </div>
    {{ csrf_field() }}
    <button type="submit" class="btn btn-default">Submit</button>
</form>

In the above HTML, I have added a file input with the name ‘profile_image’. I have also added {{ csrf_field() }} which is required to submit Laravel forms.

Now, assuming you send the post request to your controller’s store() method, write a code that stores the image on the server as below.

public function store(Request $request)
{
    if($request->hasFile('profile_image')) {
        //get filename with extension
        $filenamewithextension = $request->file('profile_image')->getClientOriginalName();

        //get filename without extension
        $filename = pathinfo($filenamewithextension, PATHINFO_FILENAME);

        //get file extension
        $extension = $request->file('profile_image')->getClientOriginalExtension();

        //filename to store
        $filenametostore = $filename.'_'.time().'.'.$extension;

        //Upload File
        $request->file('profile_image')->storeAs('public/profile_images', $filenametostore);

        //Compress Image Code Here

        return redirect('ROUTE_HERE')->with('success', "Image uploaded successfully.");
    }
}

This code creates a unique filename and stores the file inside the ‘profile_images’ directory. Laravel automatically generates a ‘profile_images’ directory under ‘public/storage’ if it does not exist.

As said before, it is a better practice to optimize the image at the time of upload. We are done with the code of uploading an image. Now we need to compress it. I am going to cover 2 services – TinyPNG and reSmush.it which provides the APIs to compress images on the fly. Let’s see them one by one.

Compress Images using TinyPNG in Laravel

To compress images using TinyPNG API you need to get your API key. The process is straight-forward. Register your email address with them and they will send your developer key.

Once you get the API key, add it in the .env file.

TINIFY_API_KEY=

After this, install a TinyPNG package using the command:

composer require tinify/tinify

Upon package installation, we have to write a code that compresses the uploaded image using TinyPNG.

Write a compression code just below the line which uploads the image.

//Compress Image Code Here
$filepath = public_path('storage/profile_images/'.$filenametostore);

try {
    \Tinify\setKey(env("TINIFY_API_KEY"));
    $source = \Tinify\fromFile($filepath);
    $source->toFile($filepath);
} catch(\Tinify\AccountException $e) {
    // Verify your API key and account limit.
    return redirect('ROUTE_HERE')->with('error', $e->getMessage());
} catch(\Tinify\ClientException $e) {
    // Check your source image and request options.
    return redirect('ROUTE_HERE')->with('error', $e->getMessage());
} catch(\Tinify\ServerException $e) {
    // Temporary issue with the Tinify API.
    return redirect('ROUTE_HERE')->with('error', $e->getMessage());
} catch(\Tinify\ConnectionException $e) {
    // A network connection error occurred.
    return redirect('ROUTE_HERE')->with('error', $e->getMessage());
} catch(Exception $e) {
    // Something else went wrong, unrelated to the Tinify API.
    return redirect('ROUTE_HERE')->with('error', $e->getMessage());
}

The above code takes an image from the uploaded directory, sends it to the TinyPNG server for compression, and after receiving a response, stores the compressed image in the same directory.

This process runs in the background. You don’t need to worry about how the image is going to the TinyPNG server, how it receives the API response. TinyPNG library does all tasks for you.

Try to upload the image now and you should see your image get compressed.

Compress Images using reSmush.it in Laravel

TinyPNG works well but it has a limitation of optimizing 500 free images per month. If you want to compress more than 500 images, you need to pay for them. Alternatively, users can pick a free service of reSmush.it for image compression. At the time of writing this article, reSmush.it compresses more than 7 billion images. This is enough to say about the popularity of this service.

So, write the code below which compresses images using reSmush.it in Laravel.

//Compress Image Code Here
$filepath = public_path('storage/profile_images/'.$filenametostore);
$mime = mime_content_type($filepath);
$output = new \CURLFile($filepath, $mime, $filenametostore);
$data = ["files" => $output];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://api.resmush.it/?qlty=80');
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result = curl_exec($ch);
if (curl_errno($ch)) {
    $result = curl_error($ch);
}
curl_close ($ch);

$arr_result = json_decode($result);

// store the optimized version of the image
$ch = curl_init($arr_result->dest);
$fp = fopen($filepath, 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
fclose($fp);

I have passed the quality value as 80 ?qlty=80 in the above code. You can play with passing different quality values.

I hope you understand how to upload and compress images in Laravel. I would like to hear your thoughts and suggestions in the comment section below.

Related Articles

If you liked this article, then please subscribe to our YouTube Channel for video tutorials.

5 thoughts on “How to Upload and Compress Images in Laravel

  1. Nice Tutorial but after uploading some images i’m getting error “Maximum execution time of 60 seconds exceeded”
    and when i remove Tinify code then it works fine but i want to use tinify to compress image size.

    try {
    \Tinify\setKey(env(“TINIFY_DEVELOPER_KEY”));
    $source = \Tinify\fromFile($realimagepath);
    $source->toFile($realimagepath);
    } catch(\Tinify\AccountException $e) {
    // Verify your API key and account limit.
    return redirect(‘admincontrol/create’)->with(‘error’, $e->getMessage());
    } catch(\Tinify\ClientException $e) {
    // Check your source image and request options.
    return redirect(‘admincontrol/create’)->with(‘error’, $e->getMessage());
    } catch(\Tinify\ServerException $e) {
    // Temporary issue with the Tinify API.
    return redirect(‘admincontrol/create’)->with(‘error’, $e->getMessage());
    } catch(\Tinify\ConnectionException $e) {
    // A network connection error occurred.
    return redirect(‘admincontrol/create’)->with(‘error’, $e->getMessage());
    } catch(Exception $e) {
    // Something else went wrong, unrelated to the Tinify API.
    return redirect(‘admincontrol/create’)->with(‘error’, $e->getMessage());
    }

    1. max_execution_time issue is related to your PHP configuration not with Laravel. You should change values of max_execution_time in your php.ini file. Set it to 300 like max_execution_time=300

Leave a Reply

Your email address will not be published. Required fields are marked *