Ajax based file uploads using FileInput plugin

There have been queries and requests from many folks who wish to learn implementing AJAX uploads with the bootstrap-fileinput jQuery plugin. How does one build the server code (e.g. PHP) for parsing the AJAX response and sending data back to the plugin? This webtip mentions a PHP server side processing example for using the bootstrap-fileinput plugin to process your ajax based uploads.

About bootstrap-fileinput

The bootstrap-fileinput jQuery plugin by Krajee is an advanced HTML 5 file input designed using Bootstrap 3.x CSS styles. It is a simple yet powerful file management tool and solution for web developers that utilizes HTML 5 and CSS 3 features (supported by most modern browsers). In addition to advanced styles & layouts, the plugin offers file preview for various files, multiple selection including drag & drop, ajax based uploads with progress bar, setting initial previews and deletes and more.

Pre-requisites

Ensure all the pre-requisites for the bootstrap-fileinput jQuery plugin are followed and adhered to. You must have the bootstrap CSS and jQuery library loaded before you run the other scripts below.

Input Markup (HTML)

Let’s consider you have the following markup to initialize the input. The scenario considered is ajax based upload of multiple images. Your markup can be as simple as below (note the id and name attributes).

<input id="images" name="images[]" type="file" multiple>

However, in many cases you may have other form fields or additional data you may need to submit. Let’s consider you have the following additional fields in your form.

<input id="userid" name="userid" type="hidden">
<input id="username" name="username" type="text">

Initialize Plugin (Javascript)

Let’s consider a simple scenario of uploading files via Ajax. You will need to setup the javascript to initialize the bootstrap fileinput plugin. Note that the examples here uses jQuery. You would like to send additional form data when the files are uploaded (i.e. user_id and user_name). You can setup all of these as mentioned below. By default the plugin will upload in asynchronous mode through parallel ajax calls. You can control that through uploadAsync property.

$(document).on("ready", function() {
    $("#images").fileinput({
        uploadAsync: false,
        uploadUrl: "/path/to/upload.php" // your upload server url
        uploadExtraData: function() {
            return {
                userid: $("#userid").val(),
                username: $("#username").val()
            };
        }
    });
});

Server Code (PHP)

Let’s look at the server code upload.php as mentioned above that will receive and process the data.

// upload.php
// 'images' refers to your file input name attribute
if (empty($_FILES['images'])) {
    echo json_encode(['error'=>'No files found for upload.']); 
    // or you can throw an exception 
    return; // terminate
}

// get the files posted
$images = $_FILES['images'];

// get user id posted
$userid = empty($_POST['userid']) ? '' : $_POST['userid'];

// get user name posted
$username = empty($_POST['username']) ? '' : $_POST['username'];

// a flag to see if everything is ok
$success = null;

// file paths to store
$paths= [];

// get file names
$filenames = $images['name'];

// loop and process files
for($i=0; $i < count($filenames); $i++){
    $ext = explode('.', basename($filenames[$i]));
    $target = "uploads" . DIRECTORY_SEPARATOR . md5(uniqid()) . "." . array_pop($ext);
    if(move_uploaded_file($images['tmp_name'][$i], $target)) {
        $success = true;
        $paths[] = $target;
    } else {
        $success = false;
        break;
    }
}

// check and process based on successful status 
if ($success === true) {
    // call the function to save all data to database
    // code for the following function `save_data` is not 
    // mentioned in this example
    save_data($userid, $username, $paths);

    // store a successful response (default at least an empty array). You
    // could return any additional response info you need to the plugin for
    // advanced implementations.
    $output = [];
    // for example you can get the list of files uploaded this way
    // $output = ['uploaded' => $paths];
} elseif ($success === false) {
    $output = ['error'=>'Error while uploading images. Contact the system administrator'];
    // delete any uploaded files
    foreach ($paths as $file) {
        unlink($file);
    }
} else {
    $output = ['error'=>'No files were processed.'];
}

// return a json encoded response for plugin to process successfully
echo json_encode($output);

Summary

That’s about a basic setup you need to do to upload files via ajax and the plugin should process it. Note, that for your practical cases you may need to tweak various other settings and add to this basic setup above. You may also need to control various other properties of the plugin to make it work the way you want for your entire application – like uploadAsync, initialPreview, initialPreviewDelete etc. Similarly, you can use the various events in the plugin to trigger or perform additional actions – e.g. filepreupload, fileuploaded etc.

43 thoughts on “Ajax based file uploads using FileInput plugin

  1. As updated on stackoverflow, you may need to check that directory for upload is readable/writable. It seems you are using this on windows (looking at the logs) and hence folder separators are important.

    Instead of forward slashes in your code use the DIRECTORY_SEPARATOR in php (so it works both on windows or unix/linux web server platforms):

    $target = "tickets" . DIRECTORY_SEPARATOR . md5(uniqid()) . "." . array_pop($ext);
    
  2. Hi,

    I want to use plug in for upload functionality but i’m not able to get the css and js correctly on page.
    Gave all the required js and cc in below order:
    Bootstrap.css
    fileinput.css
    jquery.js
    bootstrap.js

    and put
    // Scenario 2: Batch upload in synchronous mode without parallel server calls (check uploadAsync property)

    in my jsp file

    All the css and js are loading perfectly fine but i’m not able to get the css and js correctly on page.

    Please help me and let me know if i’m missing something.

    Thanks!
    CoolG

  3. Hey, I’m using dreamweaver here, and the rows for $output = []; is giving me an error.
    I just thought it had to be $output = array();
    But the second line gives me the same error:
    $output = [‘error’=>’Error while uploading ticket. Contact the system administrator’];

    For json purposes what is a better notation, cause now i’m getting this error in firefox:
    SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

    Btw, anyway to hide the upload bar after completion?
    Thanks in advance!

      1. Thanks for the response Kartik, Great plugin. I had already looked over those docs but I didn’t find what I was looking for. When I click upload I get a error No Parameterless Constructor Defined for this Object. I had modified my Controller method to take a HttpRequest object and a int ContactId for saving the data with associations but the method is not seeing that one. Is there a specific setting to pass the image[] to the server?

  4. I’ve trying to use this webtip on codeigniter but I constantly receive an error: SyntaxError: JSON.parse: unexpected keyword at line 1 column 1 of the JSON data. I read that this happens when the plugin doesn’t receive a json response but I’ve tried with other plugins and my controller responses with json. Can you help me?

    1. The best person to resolve this will be you. You need to debug and see what AJAX/JSON response is being sent by the server to client (using Firebug for Firefox or Chrome inspector). Check certain standard config params to be sure you have the right setup. For example your input name attribute (‘images’ in this example) must match the array key you pass in $_FILES (i.e. $_FILES[‘images’]) — similarly check other configurations which may be specific for your use case (you could do this best by debugging via firebug or something similar).

      1. I believe it is something wrong with the js file because my controller doesn’t receive nothing on ajax submit

        1. I do not understand – the JS file has nothing to do with your server side controller action not getting called. It will depend on what you are setting as uploadURL and the ajax call will be made using this URL. Its then upto the server to process the rest as it receives this response. As I said, you need to debug using Firebug or similar tool to check what you have passed/setup and what action is getting executed, and what is the response (output). You need to ensure that your server action can read and parse an ajax POST submission call and proceed as mentioned in the examples.

          The server code example provided here just gets you a basic idea to get it started (it does not include any other validations or application specific features and not by any means is a comprehensive code for all scenarios). You would need to build up your server code as per your web application configuration or web application framework (including any configuration needs for understanding ajax POST requests).

          PS: The plugin has been tested, used and deployed on web frameworks without any issues.

  5. Really cool plugin. Thanks for the really informative tip. Works like a piece of cake without any issues.

  6. Was routed to this from forums when searching for a yet simple file upload utility. Really great and powerful plugin with immense functionalities. Was able to set it up with all the instructions on the documentation and this article here.

    Already I could use it doing various things in a fast manner and have recently built an advanced image gallery with minimal coding.

    Just one question – it already has so many features (as I kept on finding when I used it)… could I add further actions after saved images are displayed using `initialPreview` in the easiest way – understand the otherActionbuttons – is there a recommended way?

    1. Yes you are on the right track. Use otherActionButtons to define the additional thumbnail action buttons. For example to include an edit button:

      otherActionButtons: '<button type="button" ' +
          'class="kv-file-edit btn btn-xs btn-default" ' +
          'title="Edit" {dataKey}>\n' + // the {dataKey} tag will be auto replaced
          '<i class="glyphicon glyphicon-edit"></i>\n' +
          '</button>\n'
      

      Then you can create your own javascript action to trigger the edit form or modal on click of the above button:

      $('.kv-file-edit').on('click', function() {
         var key = $(this).data('key'); // get the file key
         launch_edit_modal(key); // create a function to launch the edit form/modal dialog
      });
      
  7. Hi,

    In my site , i use your beautiful plugin for upload some photos and everything is ok..

    BUT now i have to allow users to delete their photos.,add new ones etcc

    I ‘think’ that .Ajax Upload Demo Scenario 5 should be the solution with initial-preview concept

    but i don’t understand , ( uploadUrl: is activated for uploading files)

    how can i pass the images to preview (from server) to the plugin..

    can you explain us the method ( in detail please) like you have made very well for upload in this page….

    MANY thanks

    1. You must return back a json encoded object from your server that contains the arrays initialPreview and initialPreviewConfig and you can send append as true if you need to append to initial preview. Please read in docs about the data you can send from server for sync uploads like in scenario 5 and data that you can receive as well.

      There is a PHP example server code already provided in the example for demo scenario 5 as well as demo scenario 4 – scroll below to the code section.

      1. sorry but it’ is a code that processes ajax UPLOAD ..

        BEFORE upload , i would like to have in the thumbnail the photos from the server..

        thanks

            1. I suggest to read once and understand the various options. Its difficult to be pasting a code for each scenario.

              Why you don’t see delete in advanced? Well – you need to set initialPreviewConfig for setting the delete action for files – else delete button will not be shown.

              How to put photos from server side? Well – you need to use your server code to generate the initial javascript for initializing the file input as shown. Your server code generates an HTML – so it can also generate the javascript code for initializing the file input.

              Basically there are options which can be combined – or used in isolation based on each use case – and hence you need to try them out one by one by reading them from docs.

          1. thanks

            ‘you need to use your server code to generate the initial javascript for initializing the file input’

            is it the solution ?:(or another best one)

            controller:

            // search photos for user 1
            $images = array(”,
            ”);

            $upload_script=’
            $(“#images”).fileinput({
            uploadUrl: strURL,
            uploadAsync: true,
            initialPreview: $images,
            …………………………..’;

            view:

            about initialPreviewConfig for setting the delete action for files, i don’t see the solution
            maybe url in initialpreviewconfig !(or create a button delete)

            thanks for your support..

        1. i can’t publish the code view:

          in fact in the script i would make a echo of the field upload_script

  8. Hi Kartik,
    I am trying your plugin in codeigniter PHP framework.

    This is my custom.js file
    /* Initialize your widget via javascript as follows */
    $(“#input-21”).fileinput({
    previewFileType: “image”,
    browseClass: “btn btn-success”,
    browseLabel: “Pick Image”,
    browseIcon: ‘‘,
    removeClass: “btn btn-danger”,
    removeLabel: “Delete”,
    removeIcon: ‘‘,
    uploadClass: “btn btn-info”,
    uploadLabel: “Upload”,
    uploadIcon: ‘‘,

    uploadUrl: './upload/do_upload/', // you must set a valid URL here else you will get an error
    allowedFileExtensions : ['jpg', 'png'],
    overwriteInitial: false,
    maxFileSize:8000,
    maxFilesNum: 10,
    //allowedFileTypes: ['image', 'video', 'flash'],
    slugCallback: function(filename) {
    return filename.replace('(', '_').replace(']', '_');
    }
    

    });

    /*
    $(".file").on('fileselect', function(event, n, l) {
        alert('File Selected. Name: ' + l + ', Num: ' + n);
    });
    */
    
    $(document).ready(function() {
        $("#test-upload").fileinput({
    
            'showPreview' : false,
            'allowedFileExtensions' : ['jpg', 'png','gif'],
            'elErrorContainer': '#errorBlock'
        });
        /*
        $("#test-upload").on('fileloaded', function(event, file, previewId, index) {
            alert('i = ' + index + ', id = ' + previewId + ', file = ' + file.name);
        });
        */
    

    });

    This is my view –

    Image Title

    Image Url

    <script src="”>

    This is my Controller..
    <?php
    class Upload extends CI_Controller
    {

    function __construct()
    {
        parent::__construct();
        $this->load->helper(array('form', 'url'));
        $this->load->library('form_validation');
        $this->load->model('promo');
    }
    
    function index()
    {
            $data['title'] = "Upload Promo Image";
            $this->load->view('templates/admin/header', $data);
            $this->load->view('admin/upload_promo', array('error' => '' ));
            $this->load->view('templates/admin/footer');            
    }
        public function do_upload()
        {
        $config['upload_path'] = './assets/images/uploads/promo/';
        $config['allowed_types'] = 'jpg|png';
        $config['max_size'] = '8000';
        $config['max_width'] = '3000';
        $config['max_height'] = '1900';
    
        $this->load->library('upload', $config);
    
        if ( !$this->upload->do_upload())
        {
            $data['title'] = "Upload Promo Image";
            $this->load->view('templates/admin/header', $data);
            $error = array('error' => $this->upload->display_errors());
            $this->load->view('admin/upload_promo', $error);
            $this->load->view('templates/admin/footer');            
    
        }
        else
        {
    
            $this->form_validation->set_rules('img-title','Title','required');
            $this->form_validation->set_rules('userfile','File','required');
    
                {
                $data['title'] = "Upload Promo Image";
                $this->load->view('templates/admin/header', $data);
                $data = $this->upload->data();
                $slug = $data['file_name'];
                $this->load->view('admin/upload_success');
                $this->load->view('templates/admin/footer');
                $this->promo->upload_image($slug);
                }
    
        }
        }
    

    }

    /* End of file upload.php /
    /
    Location: ./application/controllers/upload.php */

    The Error is Showing is :::::::: JSON: Paese Error. Unexpected symbol <.
    Please reply me somewhere. as i left you message in you facebook page, Twitter, and githhub.. any don’t know where not.
    Its very urgent please reply me as soon as possible.

  9. I am trying to use your file upload script and am getting an error at the place where there is the

    $(document).on(“ready”, function() {

    The error is “Uncaught TypeError: undefined is not a function”

    My includes are:

    the init script is:

    $(document).on(“ready”, function() {
    $(“#file-0”).fileinput({
    allowedFileExtensions : [‘svn’],
    uploadAsync: false,
    uploadUrl: “http://192.168.25.210:8080/sms/upload.php” // your upload server url
    /*
    uploadExtraData: function()
    {
    return
    {
    userid: $(“#userid”).val(),
    username: $(“#username”).val()
    };
    }
    */
    });
    });

    and the place where the form is:

    <div class="col-lg-10">
    <div id="clearfix"></div>
        <form enctype="multipart/form-data" id="select_file">
        <input id="file-0" class="file" type="file"name="txt_file" multiple data-min-file-count="1">
        <br>
        <button type="submit" class="btn btn-primary">Enviar</button>
        <button type="reset" class="btn btn-default">Limpar</button>
        </form>
    <div id="clearfix"></div>
    </div>
    

    Can you help me to find the error?

    Thanks

    Sergio

  10. Hi there – Great Plugin!

    I’m trying to integrate this with WordPress in a WP plugin I’m writing but having problems utilising the admin-ajax.php as I cant seem to pass my action function (in my wp plugin php file) as a parameter in your plugin call.

    Are you aware of anyone using your plugin with WordPress or have you managed to do this at all?

    I could probably do this without using the WP functions but would like to if possible.

    Once again thanks for a great plugin.

  11. Kartik,
    You are really rockstar.This plugin is very usefull for me. Is there any option to upload files on form submit? I need to upload the files if they are not uploaded on clicking on the form submit button.Thanks in advance.

  12. Kartik,

    I’m beginner to this. This plugin is very useful for me. i initiate 2 times this with different option, but “maxImageWidth: 300, maxImageHeight: 220” applying to both initiates. i no need that property values to “#floor_plan_image”. How can i fix this?

    $(“#thumbnail_image”).fileinput({
    uploadUrl: “classes/upload.class.php”,
    browseClass: “btn btn-primary btn-block”,
    uploadClass: “btn btn-default btn-block”,
    showCaption: false,
    showRemove: false,
    overwriteInitial: false,
    resizeImage: true,
    maxImageWidth: 300,
    maxImageHeight: 220,
    resizePreference: “height”,
    maxFileSize: 2000,
    allowedFileExtensions: [“jpeg”, “jpg”, “png”],
    elErrorContainer: “#thumbnail_image_errorBlock”
    });

    $(“#floor_plan_image”).fileinput({
    uploadUrl: “classes/upload.class.php”,
    browseClass: “btn btn-primary btn-block”,
    uploadClass: “btn btn-default btn-block”,
    showCaption: false,
    showRemove: false,
    maxFileSize: 2000,
    allowedFileExtensions: [“jpeg”, “jpg”, “png”],
    elErrorContainer: “#floor_plan_image_errorBlock”
    });

  13. Hi Kartik V, I developed a form (YII2 application) with your fileInput widget with asynchronous upload, I also add the ability to remove the file uploaded using the initialPreviw and the initialPreviewConfiguration. The only thing that I couldn’t get is to keep your beautiful thumbnails: when I upload the file the original thumbnails was covered with another ugly icons that I can modify changing the initialPreview but I would to keep those originals. Is it possible? Thank you for your work , Gabriella

  14. upload icon() auto deleting after file file uploaded event . how to show success icon after ajax upload. i am send initialPreview and initialPreviewConfig from server side

  15. Hey Kartik,

    I tried to use this plugin to upload image.I have few doubts:
    1. how to access the data sent from ajax @server end? i’ve created server using spring mvc.
    2. is the data sent to server a json?

  16. Great add-on… Simple question: Using the Yii widget, is there a simple way to add the delete icon to the preview images? I can then do an ajax delete upon click. Thanks for the great product!

Comments are closed.