Home > FileDrop

FileDrop

FileDrop is a project mainly written in JavaScript, it's free.

A HTML5 drag-drop file reading and uploading javascript library.

Introduction

This is a Javascript library for reading files into
browser memory and/or background uploading using
multi-file drag-drop.

This library makes use of HTML5/Javascript/CSS only.

Supported (tested) browsers so far:

  Firefox 4 (3.6 may work but not tested)
  Chrome 13 (earlier may work, but not tested)

  Safari 5.1 on Mac OS:
    File drag-drop and uploading works.
    File reading (into js memory) does not work.

  Safari 5.1 on Windows:
    Tested and does NOT work.

Checking browser capabilities:

To check if FileDrop supports the current browser, run:

  FileDrop.support();

It will return true if the browser is supported, and
false if it is not.

To check if file reading is supported use:

  FileDrop.readSupport();

It will return true if file reading is supported for the
current browser, and false if not.

To check if background file uploading is supported use:

  FileDrop.uploadSupport();

It will return true if uploading is supported for the
current browser, and false if not.

Basic usage:

Drag-drop file uploading can be activated for an html
element using:

    FileDrop.create('my_element_id', {
                    url: '/foo/upload',
                    read_files: true,
                    upload_files: true,
                    hover_class: 'my_css_class',
                    client_side_zip: true});


The file will be uploaded as if it was uploaded using
a good old-fashioned:

  <form action='/foo/upload' method='POST'>
    <input name='file' type='file' />
    <input type='submit' value='Submit'>
  </form>

my_element_id is the id of the HTML element activate 
as a file drop-zone, and is the only required 
parameter. All other parameters are optional.

The read_files parameter specifies that files should
be read into js memory when dropped onto the element.

The upload_files parameter specifies that files should
be uploaded to the given url when dropped onto the
element.

At least one of these two parameters (read_files
or upload files must be true in order to use the 
FileDrop library. If one or both of these parameters 
are specified, then the unspecified parameters will 
be set to true if the browser supports them and 
false if not.

The hover_class parameter specifies a CSS class that
will be added to the drop-zone element when the
cursor hovers over the element while files are being
dragged. The CSS class will be removed from the
element again when the cursor no longer hovers
over the element, or, if the files are dropped,
after the file receive, upload or receive+upload
has been completed.

The client_side_zip parameter specifies whether
received zip files should be extracted client side.
If this is true, then all zip files will be extracted,
discarding directory structure, and the extracted 
files will be treated as if they had been received
normally. Nested zip files will be extracted and
handled in the same way.

To use client_side_zip, you will need
the js-unzip library written by August Lilleaas:

  https://github.com/augustl/js-unzip

To handle _compressed_ zip files you also need
the js-inflate library, written by Masanao Izumo
and August Lilleaas:

  https://github.com/augustl/js-inflate/

These two libraries will allow FileDrop to handle
the following zip archive compression methods:

  * No compression: Rarely used.
  * DEFLATE: The most common zip file compression.

Note: The current version of FileDrop does not
      support mime-type detection of the files
      archived in zip files, which means that
      you can only filter compressed/archived
      files by extension, _not_ by mime-type.

Filtering:

With filtering you can allow or disallow certain
types of files from being received and/or uploaded.
Filtering works by setting either the allow or
disallow parameter when calling create.

var f = FileDrop.create('filedrop', {
                      url: '/bar/upload',

                      allow: [{
                        mime_type: 'image/jpeg',
                        extension: 'jpg'
                      },{
                        extension: 'txt'
                      }]
                     });

If allow is specified, only files matching one or more 
of the rules are allowed.

If disallow is specified, only file matching one or more
of the rules are disallowed.

If no filters are specified then all files are allowed.

You must never specify both allow and disallow parameters
for the same call to create.

The allow and disallow parameters are both an array of 
one or more rules.

A rule is a hash that looks something lige e.g:

  {mime_type: 'image/jpeg', extension: 'jpg'}

You can omit either mime_type or extension, but not both.

If the above rule is used like so:

FileDrop.create('droparea', {

  allow: [
    {mime_type: 'image/jpeg', extension: 'jpg'}
  ]
});

Then only files with the image/jpeg mimetype and the
extension 'jpeg' will be allowed.

Extensions and mimetypes are matched case-insensitive.

Callback API:

To use the FileDrop API, first instantiate:

  var f = FileDrop.create(...);

The callback API is documented using commented examples:

/* 
  Called when a file is disallowed based on allow or 
  disallow rules. The rules variable is an array of 
  the rules that triggered the disallow.
  An empty array means that the file was disallowed
  because the default is to disallow and no specific
  allow rule matched.
*/
f.on_disallowed_file = function(file, rules) {
  console.log("File " + file.name + " was disallowed based on " + rules.length + " rules");

}

/* 
  Called when a file is allowed based on allow or 
  disallow rules. The rules variable is an array of 
  the rules that triggered the allow.
  An empty array means that the file was allowed
  because the default is to allow and no specific
  disallow rule matched.
*/
f.on_allowed_file = function(file, rules) {
  console.log("File " + file.name + " was allowed based on " + rules.length + " rules");
}

/*
  Receiving (client side) is about to begin.
  Called only once per drop.
  "Some files (one or more) are about to be received."
*/
f.on_receive_begin = function(files) {
  console.log("Some files were dropped! (actually " + files.length + ")");
};

/*
  Files were successfully received (client side).
  Called only once per drop.
  "All the files that were to be received have now been received."
*/
f.on_receive_completed = function(files) {
  console.log("Received files: " + files.length);
};

/*
  Receiving a file (client side) is about to begin.
*/
f.on_receive_file_begin = function(file) {
  console.log("Receiving file: " + file);
};

/*
  Called repeatedly while a file is being received (client side).
  Use this for e.g. progress bar updates.
*/
f.on_receive_file_progress = function(file, bytes_received, bytes_total) {
  console.log("Receive progress for: " + bytes_received + " of " + bytes_total);
};  

/*
  A file was received (client side) successfully.
*/
f.on_receive_file_completed = function(file) {
  var str = "Received a file: " + file;
  if(file.is_archive) {
    str += ' [archive]';
  }
  if(file.parent_archive) {
    str += ' [from archive: ' + file.parent_archive.name + ']';
  }
  console.log(str);
};

/*
  Upload of file(s) is about to begin.
  Called only once per drop.
*/
f.on_upload_begin = function(files) {
  console.log("Beginning upload of " + files.length + " files");
};

/*
  Upload of all dropped files has completed.
  Called only once per drop
*/
f.on_upload_complete = function(files) {
  $('filedrop').innerHTML = "Finished uploading " + files.length + " files.";
  console.log("All uploads completed");
};

/*
  Upload of a file is about to begin.
*/
f.on_upload_file_begin = function(file) {
  console.log("File upload started: " + file.name);
};

/*
  Called during upload of each file.
  Use this to update e.g. an upload progress bar.
*/
f.on_upload_file_progress = function(file, bytes_received, bytes_total) {
  console.log("File upload progress: " + bytes_received + " of " + bytes_total);
};

/*
  A single file was successfully uploaded.
*/
f.on_upload_file_complete = function(file, bytes_received) {
  console.log("Uploaded file: " + file.name + " in " + bytes_received + " bytes");
};

/*
  An error (e.g. a 404) occurred while attempting to upload.
*/
f.on_upload_error = function(http_status, http_response) {
  console.log("Error with http status " + http_status + " and response: " + http_response);
};

/*
  If an in-progress upload is aborted.
  E.g. the user clicked 'stop' in the browser or hit escape.
*/
f.on_upload_aborted = function() {
  console.log("Upload aborted.");
};

/*
  Happens when the compression method used for a file in
  an archive is not supported.
*/
f.on_decompression_error = function(file, msg) {
  console.log("Error decompressing file '" + file.name + "' in archive '" + file.parent_archive.name + "': " + msg);
};

/*
  Files being dragged entered the drop-area.
  Like onmouseenter when dragging files.
*/
f.on_droparea_enter = function() {
  console.log("Files are being held over drop-aerea.");
};

/*
  Files being dragged exited the drop-area.
  Like onmouseout when dragging files.
*/
f.on_droparea_exit = function() {
  console.log("Hanging files exited drop-area.");
};


/*
  TODO add an on_drop callback
*/