Technically Feasible

File validation with jQuery and HTML5

Likeness of Michael Oldroyd
Michael Oldroyd
⚠️ This content was imported from a previous incarnation of this blog, and may contain formatting errors

I have been dealing with file uploads a lot recently, and I stumbled upon a few different methods for validating files which provide both basic file-type checking and file size checking before uploading.

The web app was already making use of jQuery with the excellent jQuery validation plugin; so I wrote a couple of extended validators.

File type validation (via file extension) #

This defines an regular expression of valid file extensions, which we currently define as gif, jpeg/jpg and png.

This form of validation is quite widely supported; the file input exposes a file path (sometimes a fake path) along with the filename of the original file.

/**
* Basic file type validation support for common web-safe image formats.
*
* @date 2011-09-22
* @author Michael Oldroyd
* @version 1.0
*/
$.validator.addMethod(
"image",
function(value, element) {
if ($(element).attr('type') == "file"
&& ($(element).hasClass('required')
|| $(element).get(0).value.length > 0))
return value.match(/\.([png|gif|jpg|jpeg])$/i);
else
return true;
},
"Invalid file type. Only PNG, JPEG and GIF formats are supported"
);

File size validation #

This validator makes use of some of the HTML5 file APIs.This means that it won't work with browsers which haven't implemented the HTML5 File API module. The two methods we are interested with are window.File and window.FileList. We check for these first, and automatically "pass" the validator if they aren't available so that it gracefully degrades.

The validator supports multiple files per input, and multiple file inputs per form. So each time the validator fires, we find all file inputs in the form; iterating over each, accessing the files property and iterating this too. Each time we increment the total size (in bytes) with the size of the file in the list.

If the files attached exceed the MAX_FILE_SIZE input element's value, the validator fails; otherwise it passes. If no element named MAX_FILE_SIZE is found, the validator also passes as we have no basis for comparison.

/**
* Provides file upload limit validation, according to server rules (i.e.
* MAX_UPLOAD_FILESIZE). This validator uses a MAX_FILE_SIZE input element
* and checks the total size of selected file(s) against this value.
*
* @date 2011-09-23
* @author Michael Oldroyd
* @version 1.0
*/
$.validator.addMethod(
 "filesize",
 function(value, element) {
  if (window.File && window.FileList) {
   if ($(element).attr('type') == "file"
    && ($(element).hasClass('required')
    || element.files.length > 0)) {
    var size  = 0;
    var $form = $(element).parents('form').first();
    var $fel = $form.find('input[type=file]');
    var $max = $form.find('input[name=MAX_FILE_SIZE]').first();
    if ($max) {
     for (var j=0, fo; fo=$fel[j]; j++) {
      files  = fo.files;
      for (var i=0, f; f=files[i]; i++) {
       size += f.size;
      }
     }
     return size <= $max.val();
    }
   }
  }
  return true;
 },
 "The file(s) selected exceed the file size limit. Please choose another file."
);

Click here for the demo

The code for this example was in part inspired by the work of Eric Bidelman at HTML5 Rocks.

It's also worth noting that I don't claim that these implementations are perfect, so I would welcome any improvements or suggestions to improve the validators above.

Image of me

Michael Oldroyd

Michael is a Software Engineer working in the North West of England.