jQuery MultiFile

The unopinionated way to implement file selection.

What this is

This jQuery Multiple File Selection Plugin ($.MultiFile) is a non-obstrusive plugin for jQuery that helps users easily select multiple files for upload. It lets you apply some basic restrictions/validation so you can easily reject files before they're uploaded based on their extension or size before they're uploaded.

What this isn't

This is not a file upload tool. Uploading files require server-side integration and security considerations this project will never support. We can recommend many, many, many great tools if you're looking for a complete upload solution. But if you don't already manage your own server-side integration, or if you have no idea what I'm talking about, then this plugin is not for you.

What's new?

A fresh start... ish : This project started a a very long time ago... and it's been dormant since 2009! Support has been shockingly bad, we admit, but we would like to engage more actively with our users and the jQuery community from now on. So as of April 2014, we've left Google Code behind and will be starting a fresh project on GitHub. Our other projects (Star Rating & CKEditor will follow shortly). We very much encourage and would love you all to report issues, contribue and discuss this project on GitHub.

Getting started

Just add the multi class to your file input element.

<input type="file" class="multi"/>

Use the maxlength property if you want to limit the number of files selected.

<input type="file" class="multi" maxlength="2"/>

Use the accept property if you only want files of a certain extension to be selected.
Separate valid extensions with a "|", like this: "jpg|gif|png".

<input type="file" class="multi" accept="gif|jpg"/>
NB.: server-side validation is always required

Usage Examples

Using Attributes

The easiest way to get started is to add class="multi" and modify the attributes of your element

Example 1

Use maxlength to limit the number of files selected

<input
  class="multi"
  maxlength="2"
/>
Limit: 2 files.
Allowed extensions: any.
Example 2

Use accept to limit the extensions allowed

<input
  class="multi"
  accept="gif|jpg"
/>
Limit: no limit.
Allowed extensions: gif and jpg.
Example 3

Use maxlength and accept combined

<input
  class="multi"
  accept="gif|jpg"
  maxlength="3"
/>
Limit: 3 files
Allowed extensions: gif, jpg.
Note that server-side validation is always required

Using the class property

There is a way to configure the plugin via the class property, without any knowledge of javascript

Example 4
<input class="
  multi max-3
"/>
Limit: 3 files.
Allowed extensions: any.
Example 5
<input class="
  multi accept-gif|jpg
"/>
Limit: no limit.
Allowed extensions: gif, jpg.
Example 6
<input class="
  multi
  max-3
  accept-gif|jpg
  maxsize-1024
"/>
Limit: 3 files
Allowed extensions: gif, jpg.
Max payload: 1MB (1024 bytes)
Note that server-side validation is always required

Selecting many files at once (HTML5)

So far, each of the example above has only enabled you to select one file at a time. To select multiple files at once, just use HTML5's multiple attribute (1, 2)

Example 7
<input
  multiple
  class="multi"
  maxlength="10"
/>
Limit: 10 files.
Allowed extensions: any.
Example 8
<input
  multiple
  class="multi"
  accept="gif|jpg|png"
/>
Limit: no limit.
Allowed extensions: gif, jpg.
Example 9
<input
  multiple
  class="multi"
  maxlength="10"
  accept="gif|jpg|png"
/>
Limit: 10 files
Allowed extensions: gif, jpg, png.
Note that server-side validation is always required

Validating Sizes

It's common to validate the size of the files being selected prior to upload.

Example 10a

Using class maxsize-* (* = max size in kb)

<input
  multiple
  class="multi maxsize-5120"
/>
Limit: any number of files
Allowed extensions: any.
Max payload: 5MB
Example 10b

Using data-maxsize attribute (max size in kb)

<input
  multiple
  class="multi"
  maxlength="3"
  data-maxsize="1024"
/>
Limit: 3 files (under <1MB in total)
Example 10c

Use data-maxfile to validate individual files

<input
  multiple
  class="multi"
  maxlength="3"
  data-maxfile="1024"
/>
Limit: 3 files (under <1MB each)
Note that server-side validation is always required

With an Image Preview

There's an easy way to add a preview of the image being uploaded

Example 11a

Using class with-preview

<input
  multiple
  class="multi with-preview"
/>

Advanced Examples

IMPORTANT: Don't use class="multi" if you use any of the examples below this point.

If you use class="multi" the plugin will be initialised automatically (taking precedence over your code).

You must invoke the plugin with your own selector when you use any of the examples below.

Something like
<input type="file" class="this-is-your-class" />
.
Followed by
// this is your code
$(function(){ // wait for page to load
  
  // this is your selector
  $('input.this-is-your-class').MultiFile({
    // your options go here
    max: 2,
    accept: 'jpg|png|gif'
  });

});

Setting limit via script

<input multiple type="file" id="UpTo3Files"/>
// wait for document to load
$(function(){
  
  // up to 3 files can be selected

  // invoke plugin
  $('#UpTo3Files').MultiFile(5);

  // if you send in a number the plugin
  // will treat it as the file limit

});
Try it:

Limit and Extension Filter

<input multiple type="file" id="UpTo3Images"/>
// wait for document to load
$(function(){
  
  // up to 3 files can be selected
  // only images are allowed

  // invoke plugin
  $('#UpTo3Images').MultiFile({
    max: 3, 
    accept: 'gif|jpg|png'
  });

});
Try it:

Multi-lingual support

<input multiple type="file" id="EmPortugues"/>
// wait for document to load
$(function(){
  
  // use a different language
  // $file prints the file name
  // $ext prints the file extension

  // invoke plugin
  $('#EmPortugues').MultiFile({ 
    max: 3, 
    accept: 'gif|jpg|png'
    STRING: { 
      remove:'Remover', 
      selected:'Selecionado: $file', 
      denied:'Invalido arquivo de tipo $ext!' 
    } 
  });

});
Try it:

Moving the file list

This example populates the file list in a custom element

$(function() { // wait for document to load 
  $('#T7').MultiFile({
    list: '#T7-list'
  });
});
This is div#T7-list - selected files will be populated here...

Customising the file list

Use a custom 'remove' image in the file list

$(function() { // wait for document to load 
  $('#T8A').MultiFile({
    STRING: {
      remove: '<img src="/i/bin.gif" height="16" width="16" alt="x"/>'
    }
  });
});

Customising all list content

$(function() { // wait for document to load 
  $('#T8B').MultiFile({
    STRING: {
      file: '<em title="Click to remove" onclick="$(this).parent().prev().click()">$file</em>',
      remove: '<img src="/i/bin.gif" height="16" width="16" alt="x"/>'
    }
  });
});

Using events

The arguments passed on to each event handler are:
element: file element which triggered the event
value: the value of the element in question
master_element: the original element containing all relevant settings

Selection events:

  • onFileAppend
  • afterFileAppend
  • onFileSelect
  • afterFileSelect
  • onFileRemove
  • afterFileRemove

Validation events:

  • onFileDuplicate
  • onFileInvalid
  • onFileTooMany
  • onFileTooBig
  • onFileTooMuch

<input multiple type="file" id="WithEvents"/>
// wait for document to load
$(function(){
  
  // 2 jpgs under 100kb only

  $('#WithEvents').MultiFile({
    max: 2,
    max_size: 100,
    accept: 'jpg|png|gif',
    onFileRemove: function(element, value, master_element) {
      $('#F9-Log').append('<li>onFileRemove - ' + value + '</li>')
    },
    afterFileRemove: function(element, value, master_element) {
      $('#F9-Log').append('<li>afterFileRemove - ' + value + '</li>')
    },
    onFileAppend: function(element, value, master_element) {
      $('#F9-Log').append('<li>onFileAppend - ' + value + '</li>')
    },
    afterFileAppend: function(element, value, master_element) {
      $('#F9-Log').append('<li>afterFileAppend - ' + value + '</li>')
    },
    onFileSelect: function(element, value, master_element) {
      $('#F9-Log').append('<li>onFileSelect - ' + value + '</li>')
    },
    afterFileSelect: function(element, value, master_element) {
      $('#F9-Log').append('<li>afterFileSelect - ' + value + '</li>')
    },
    onFileInvalid: function(element, value, master_element) {
      $('#F9-Log').append('<li>onFileInvalid - ' + value + '</li>')
    },
    onFileDuplicate: function(element, value, master_element) {
      $('#F9-Log').append('<li>onFileDuplicate - ' + value + '</li>')
    },
    onFileTooMany: function(element, value, master_element) {
      $('#F9-Log').append('<li>onFileTooMany - ' + value + '</li>')
    },
    onFileTooBig: function(element, value, master_element) {
      $('#F9-Log').append('<li>onFileTooBig - ' + value + '</li>')
    },
    onFileTooMuch: function(element, value, master_element) {
      $('#F9-Log').append('<li>onFileTooMuch - ' + value + '</li>')
    }
  });
});
This is div#F9-Log - selected files will be populated here...

Multi-lingual support

The plugin doesn't have any additional languages built-in, but it's very easy to customise the messages to any language of your choosing. See the examples below...

NB.: This example has been configured to accept gif/pg files only in order to demonstrate the error messages.

Method 1: Using class property (requires the MetaData plugin)

<input type="file"
  class="multi {
    accept:'gif|jpg',
    max:3,
    STRING:{ 
      remove:'Remover', 
      selected:'Selecionado: $file', 
      denied:'Invalido arquivo de tipo $ext!', 
      duplicate:'Arquivo ja selecionado:\n$file!' 
    } 
  }"
/>

Method 2: Programatically by ID (ONE element only, does not require MetaData plugin)

<input type="file" id="PortugueseFileUpload" />
$(function(){
  $('#PortugueseFileUpload').MultiFile({
    accept:'gif|jpg', 
    max:3, 
    STRING: {
      remove:'Remover',  
      selected:'Selecionado: $file', 
      denied:'Invalido arquivo de tipo $ext!', 
      duplicate:'Arquivo ja selecionado:\n$file!'
    }
  });
});

Method 3: Programatically ( n emlements, does not require MetaData plugin)

See this feature request for details
<input type="file" class="multi-pt" />
<input type="file" class="multi-pt" />
<input type="file" class="multi-pt" />
$(function(){
  $('.multi-pt').MultiFile({
    accept:'gif|jpg', 
    max:3, 
    STRING: { 
      remove:'Remover', 
      selected:'Selecionado: $file', 
      denied:'Invalido arquivo de tipo $ext!', 
      duplicate:'Arquivo ja selecionado:\n$file!'
    }
  });
});

Installation

Requirements

You'll need jQuery, we recommend using Google Hosted Libraries.

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js" type="text/javascript" language="javascript"></script>

The plugin

Either download the latest version and host it on your own server

<script src="path/to/your/jquery.MultiFile.js" type="text/javascript" language="javascript"></script>

OR if you like living on the edge, hotlink the latest release directly from GitHub

<script src="//github.com/fyneworks/multifile/blob/master/jQuery.MultiFile.min.js" type="text/javascript" language="javascript"></script>

Support

We very much encourage and would love you all to report issues, contribue and discuss this project on GitHub.

There's also a README.md for quick reference, if you're that way inclined.

This project started a a very long time ago... and it's been dormant since 2009! Support has been shockingly bad, we admit, but we would like to engage more actively with our users and the jQuery community from now on. So as of April 2014, we've left Google Code behind and will be starting a fresh project on GitHub. Our other projects (Star Rating & CKEditor will follow shortly).

Credit where it's due!

  • Fyneworks.com professional web design and google SEO experts
  • Dean Edwards - Author of JS Packer used to compress the plugin
  • Adrian Wr√≥bel - Fixed a nasty bug so the script could work perfectly in Opera
  • Jonas Wagner - Modified plugin so newly created elements are an exact copy of the original element (ie.: persists attributes)
  • Mike Alsup - Author of several jQuery Plugins...
    • Suggested solution to element naming convention / server-side handling
    • Form plugin - Used to submit forms via ajax
    • blockUI plugin - Used to show pretty error messages
  • Julien Phalip - Identified conflict with variable name 'class' in several methods

License Info

Multiple File Selection Plugin by Fyneworks.com is licensed, as jQuery is, under the MIT License. Creative Commons License