In Laravel5.1, image drag/drop upload and deletion are implemented based on Dropzone. js.

Source: Internet
Author: User
In Laravel5.1, image drag/drop upload and deletion are implemented based on Dropzone. js. note: This tutorial code applies to Laravel 5.1.

1. Overview

Dropzone is currently the best free drag/drop file Upload Library. it has many features and options so that you can customize it in multiple ways.

Integrating Dropzone with Laravel is a bit tricky for beginners who are not experienced, so I want to show you the most elegant solution.

This tutorial includes the following content:

  • Automatic image Upload
  • Remove images directly from Dropzone preview using Ajax requests
  • Upload image counters
  • Save the full size image and icon size version
  • Use the Intervention Image package to adjust the Image size and encoding
  • Save image data to database
  • Generate a unique image name on the server

If you still need to upload or crop images, refer to the previous tutorial: Use the jQuery plug-in Croppic + Intervention Image in Laravel 5 to upload and crop images.

The complete code for this tutorial is published on GitHub:

The final demonstration is as follows:

2. basic project configuration

Here we install a new Laravel application and create a. env file containing the database creden.

We also need to download style and script files from the that are stored in public/packages/dropzone.

We still use Bootstrap at the front end, and the relevant files are stored in public/packages/bootstrap.

As mentioned above, we need to use the Intervention Image extension package to process uploaded images, and here we will use html auxiliary functions in the Blade template. Therefore, we need to install related dependencies. to install Intervention Image, refer: intervention Image is integrated in Laravel 5 to create, modify, and compress images. for details about how to install html, see HtmlBuilder and URL: asset () in Laravel 5 () introduce css and js files on or off the site.

3. View

This tutorial only contains a single page for uploading images. although I prefer to separate the layout from the specific implementation page, we edit the layout file layout. blade. php as follows:

     Image upload in Laravel 5.1 with Dropzone.js    
     {!! HTML::style('/packages/bootstrap/css/bootstrap.min.css') !!}    {!! HTML::style('/assets/css/style.css') !!}    {!! HTML::script('') !!}    @yield('head')

Dropzone + Laravel

  • Upload



Next we will create a view file pages/upload. blade. php for uploading images:

@extends('layout')@section('head')    {!! HTML::style('/packages/dropzone/dropzone.css') !!}@stop@section('footer')    {!! HTML::script('/packages/dropzone/dropzone.js') !!}    {!! HTML::script('/assets/js/dropzone-config.js') !!}@stop@section('content')    

{!! Form::open(['url' => route('upload-post'), 'class' => 'dropzone', 'files'=>true, 'id'=>'real-dropzone']) !!}

Drop images in this area {!! Form::close() !!}

  • Images are uploaded as soon as you drop them
  • Maximum allowed size of image is 8MB

Check Created with Sketch.

error Created with Sketch.


In the head section of the upload view, we introduced the default Dropzone style. in the footer section, we passed the default JavaScript file and our own Dropzone configuration file.

The content part contains two parts: upload the form and then the hidden image preview area. I downloaded the preview template code from the Dropzone official website, use this template in the configuration file to tell Dropzone which HTML is used to upload image preview.

4. Dropzone configuration

For details about how to view the complete Dropzone configuration list, refer to here. For this project, I want to upload files one by one from Dropzone, because in this case, I do not need to traverse the file upload cyclically, the maximum number of concurrently uploaded files is 100, and the size of each file cannot exceed 8 MB.

Each image preview corresponds to a deletion link. clicking the Dropzone link triggers the removedfile event, which creates an upload/delete Ajax request. if the response status code is 200, the corresponding image counter is reduced.

var photo_counter = 0;Dropzone.options.realDropzone = {    uploadMultiple: false,    parallelUploads: 100,    maxFilesize: 8,    previewsContainer: '#dropzonePreview',    previewTemplate: document.querySelector('#preview-template').innerHTML,    addRemoveLinks: true,    dictRemoveFile: 'Remove',    dictFileTooBig: 'Image is bigger than 8MB',    // The setting up of the dropzone    init:function() {        this.on("removedfile", function(file) {            $.ajax({                type: 'POST',                url: 'upload/delete',                data: {id:},                dataType: 'html',                success: function(data){                    var rep = JSON.parse(data);                    if(rep.code == 200)                    {                        photo_counter--;                        $("#photoCounter").text( "(" + photo_counter + ")");                    }                }            });        } );    },    error: function(file, response) {        if($.type(response) === "string")            var message = response; //dropzone sends it's own error messages in string        else            var message = response.message;        file.previewElement.classList.add("dz-error");        _ref = file.previewElement.querySelectorAll("[data-dz-errormessage]");        _results = [];        for (_i = 0, _len = _ref.length; _i < _len; _i++) {            node = _ref[_i];            _results.push(node.textContent = message);        }        return _results;    },    success: function(file,done) {        photo_counter++;        $("#photoCounter").text( "(" + photo_counter + ")");    }}

The image counter is added at the bottom of the configuration file if the file is uploaded successfully.

5. Upload logic

I am used to putting specific Logic into the Repository class. in this project, I use the ImageRepository class, which is stored in app/Logic/Image/ImageRepository. php.

Currently, this class only supports two tasks: uploading a single file and deleting a specified file. we inject the entire Repository class into ImageController:

 image = $imageRepository;    }    public function getUpload()    {        return view('pages.upload');    }    public function postUpload()    {        $photo = Input::all();        $response = $this->image->upload($photo);        return $response;    }    public function deleteUpload()    {        $filename = Input::get('id');        if(!$filename)        {            return 0;        }        $response = $this->image->delete( $filename );        return $response;    }}

Therefore, for this controller, I need three routes: Display the upload form, upload and delete requests:

Route::get('/', ['as' => 'upload', 'uses' => 'ImageController@getUpload']);Route::post('upload', ['as' => 'upload-post', 'uses' =>'ImageController@postUpload']);Route::post('upload/delete', ['as' => 'upload-remove', 'uses' =>'ImageController@deleteUpload']);

The postUpload method of ImageController forwards user upload requests to the upload method corresponding to the ImageRepository class. This upload method first verifies the input, assigns a unique file name to the uploaded file, saves the original size image to the specified directory, and saves the icon size image to other directories, in addition, it must be saved to the database so that Laravel can track image upload records. Therefore, we need to create a migration file and run the migration command:

 increments('id');            $table->text('original_name');            $table->text('filename');            $table->timestamps();        });    }    /**     * Reverse the migrations.     *     * @return void     */    public function down()    {        Schema::drop('images');    }}

I have mentioned that the uploaded files will be saved in two sizes. In addition, thumbnails may be generated and encoded. to implement these features, we need to use the Intervention Image extension package:

 fails()) {            return Response::json([                'error' => true,                'message' => $validator->messages()->first(),                'code' => 400            ], 400);        }        $photo = $form_data['file'];        $originalName = $photo->getClientOriginalName();        $originalNameWithoutExt = substr($originalName, 0, strlen($originalName) - 4);        $filename = $this->sanitize($originalNameWithoutExt);        $allowed_filename = $this->createUniqueFilename( $filename );        $filenameExt = $allowed_filename .'.jpg';        $uploadSuccess1 = $this->original( $photo, $filenameExt );        $uploadSuccess2 = $this->icon( $photo, $filenameExt );        if( !$uploadSuccess1 || !$uploadSuccess2 ) {            return Response::json([                'error' => true,                'message' => 'Server error while uploading',                'code' => 500            ], 500);        }        $sessionImage = new Image;        $sessionImage->filename      = $allowed_filename;        $sessionImage->original_name = $originalName;        $sessionImage->save();        return Response::json([            'error' => false,            'code'  => 200        ], 200);    }    public function createUniqueFilename( $filename )    {        $full_size_dir = Config::get('images.full_size');        $full_image_path = $full_size_dir . $filename . '.jpg';        if ( File::exists( $full_image_path ) )        {            // Generate token for image            $imageToken = substr(sha1(mt_rand()), 0, 5);            return $filename . '-' . $imageToken;        }        return $filename;    }    /**     * Optimize Original Image     */    public function original( $photo, $filename )    {        $manager = new ImageManager();        $image = $manager->make( $photo )->encode('jpg')->save(Config::get('images.full_size') . $filename );        return $image;    }    /**     * Create Icon From Original     */    public function icon( $photo, $filename )    {        $manager = new ImageManager();        $image = $manager->make( $photo )->encode('jpg')->resize(200, null, function($constraint){$constraint->aspectRatio();})->save( Config::get('images.icon_size')  . $filename );        return $image;    }    /**     * Delete Image From Session folder, based on original filename     */    public function delete( $originalFilename)    {        $full_size_dir = Config::get('images.full_size');        $icon_size_dir = Config::get('images.icon_size');        $sessionImage = Image::where('original_name', 'like', $originalFilename)->first();        if(empty($sessionImage))        {            return Response::json([                'error' => true,                'code'  => 400            ], 400);        }        $full_path1 = $full_size_dir . $sessionImage->filename . '.jpg';        $full_path2 = $icon_size_dir . $sessionImage->filename . '.jpg';        if ( File::exists( $full_path1 ) )        {            File::delete( $full_path1 );        }        if ( File::exists( $full_path2 ) )        {            File::delete( $full_path2 );        }        if( !empty($sessionImage))        {            $sessionImage->delete();        }        return Response::json([            'error' => false,            'code'  => 200        ], 200);    }    function sanitize($string, $force_lowercase = true, $anal = false)    {        $strip = array("~", ""`, "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "+", "[", "{", "]",            "}", "\\", "|", ";", ":", "\"", "'", "‘", "’", "“", "”", "–", "—",            "—", "–", ",", "<", ".", ">", "/", "?");        $clean = trim(str_replace($strip, "", strip_tags($string)));        $clean = preg_replace('/\s+/', "-", $clean);        $clean = ($anal) ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean ;        return ($force_lowercase) ?            (function_exists('mb_strtolower')) ?                mb_strtolower($clean, 'UTF-8') :                strtolower($clean) :            $clean;    }}

The upload method verifies the field rules specified in the Image model. Currently, this rule only limits the extension of the uploaded Image.

After the upload method, we use the reateUniqueFilename method to return a unique file name for the image.

When a unique file name is returned, the image and the corresponding file name are passed to the original method, which stores the complete size image and processes the small size image using the icon method.

After the two size images are saved, the system creates a new record in the image table images.

You may have noticed that I have stored the image upload directory in the configuration file. of course, you can customize the storage directory or directly use the Laravel built-in method.

  env('UPLOAD_FULL_SIZE'),    'icon_size'   => env('UPLOAD_ICON_SIZE'),];

To make the application work normally, you also need to copy the. env. example file to the. env file and set the corresponding configuration value. Note that the upload Directory of the last two configuration items must end with a slash (/). take my local configuration as an example:


The delete method receives the file name and checks whether the database contains the file. then, the image is deleted if both of the files exist in the specified directory.

To upload images more easily using DropzoneJS, you can use the Laravel extension package Dropzoner.

Statement: This article is translated, original:

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.