I show you how to upload, resize and store images using the open-spurce PHP package Intervention Image.

 

Step 1: Create your project

After installing the Laravel framework on our machine, we create a new project with the following command:

laravel new file-upload

After the installation is complete, we use the console to install the package which is required to change the size of our uploaded image:

composer require intervention/image

 

Step 2: Setup Intervention Image package

Now we are setting up our project according to the documentation of InterventionImage.

After you have installed Intervention Image, open your Laravel config file config/app.php and add the following lines.

In the $providers array add the service providers for this package.

Intervention\Image\ImageServiceProvider::class

Add the facade of this package to the $aliases array.

'Image' => Intervention\Image\Facades\Image::class

 

Optional we can publish the config file of the package to the config directory of our project.

php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravelRecent"

For older versions of Laravel use the following command:

php artisan config:publish intervention/image

 

Step 3: Link the Laravel storage directory

We need to create a shortcut to the storage directory in order to access it from the public directory. Use the following command, which will create a shortcode called storage at your public directory.

php artisan storage:link

 

Step 4: Create controller and a basic view

Create an upload controller called ImageUpladContoller:

php artisan make: controller ImageUploadController

In the next step we will create a basic view to output our html layout. Create a file with the name upload.blade.php at the location resources/views and fill it with the following lines of code:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    <title>{{ config('app.name', 'Laravel') }} - @yield('title')</title>
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="col">
          <form method="post" action="/image/upload" enctype="multipart/form-data">
            <div class="form-group">
              <label>Upload image</label>
              <input type="file" class="form-control-file" name="image">
            </div>
            <div class="form-group">
              <button type="submit" name="submit">Upload</button>
            </div>
          </form>
        </div>
      </div>
    </div>
  </body>
</html>

Add the route to the routes/web.php file, used in the form. The route calls the upload method, which we’ll create in the next step.

Route::post('/image/upload', 'ImageUploadController@upload');

 

Step 5: Fill the ImageUploadController with code
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Image;

class DeviceController extends Controller
{
    /**
     * Uploads a new image.
     *
     * @param mixed $request
     * @author Niklas Fandrich
     * @return mixed
     */
    public function upload(Request $request) {
      $this->validate($request, [
        'image' => 'image|mimes:jpeg,png,jpg,gif,svg',
      ]);

      $this->storeImage($request);
    }


    /**
     * Prepares a image for storing.
     *
     * @param mixed $request
     * @author Niklas Fandrich
     * @return bool
     */
    public function storeImage($request) {
      // Get file from request
      $file = $request->file('image');

      // Get filename with extension
      $filenameWithExt = $file->getClientOriginalName();

      // Get file path
      $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);

      // Remove unwanted characters
      $filename = preg_replace("/[^A-Za-z0-9 ]/", '', $filename);
      $filename = preg_replace("/\s+/", '-', $filename);

      // Get the original image extension
      $extension = $file->getClientOriginalExtension();

      // Create unique file name
      $fileNameToStore = $filename.'_'.time().'.'.$extension;

      // Refer image to method resizeImage
      $save = $this->resizeImage($file, $fileNameToStore);

      return true;
    }

    /**
     * Resizes a image using the InterventionImage package.
     *
     * @param object $file
     * @param string $fileNameToStore
     * @author Niklas Fandrich
     * @return bool
     */
    public function resizeImage($file, $fileNameToStore) {
      // Resize image
      $resize = Image::make($file)->resize(600, null, function ($constraint) {
        $constraint->aspectRatio();
      })->encode('jpg');

      // Create hash value
      $hash = md5($resize->__toString());

      // Prepare qualified image name
      $image = $hash."jpg";

      // Put image to storage
      $save = Storage::put("public/images/{$fileNameToStore}", $resize->__toString());

      if($save) {
        return true;
      }
      return false;
    }

}

Explanation:

  • In the upload method we validate the image and pass it to the storeImage method.
  • The storeImage method analyzes the image and creates a unique file name.
  • In the resizeImage method we finally call the Image class, change the size of the image and save it in the storage directory.

The uploaded image should now be available at the following URL:
http://localhost/storage/images/filename.jpg

Now you can store the filename at a database and display it in your views, e.g. like this:

<img src="{{ $url('/') }}/storage/images/{{ $filename }}" alt="An image">

Sources: