XHR2 upload using Drupal 7's ajax framework I'm trying to implement XHR level 2 (file API upload) using Drupal 7's JQuery $.ajax implementation. I've got the feeling I'm almost there.

First of all, I got XHR.send() working according to orginal example on HTML5 demos. But now, I want to use Drupal 7's built in ajax framework.

I found some examples how do this with JQuery but I can't get it working for Drupal 7 with a custom ajax responce. I also found a related (D8) discussion about this on drupal.org.

Here's the code, which returns a ajax error "Illegal invocation". Probably because formData is not in a proper format?

    // 'files' below is a correct object with at least one file

    var file = files[0];
    var formData = new FormData();

    formData.append('file', files[0]);

    // element_settings: see ajax.js in drupal
    var element_settings = {};

    element_settings.progress = { 'type': 'none' }; 
    element_settings.url = '/mymodule/save/ajax';
    element_settings.data = file;
    element_settings.cache = false; 
    element_settings.contentType = file.type;
    element_settings.processData = false;
    element_settings.submit = {
      'savedata': formData
    };

    element_settings.xhr = function() {
      myXhr = $.ajaxSettings.xhr();
      if (myXhr.upload) {
        myXhr.upload.addEventListener('progress', progressHandlerFunction, false);
      } else {
        console.log("Upload progress is not supported.");
      }
      return myXhr;
    };


    var base = '#myelement';
    ajax = new Drupal.ajax(base, $('#myelement'), element_settings); 
    ajax.eventResponse($(ajax.element));


On the server site, I'm using a menu hook with ajax_deliver as delivery callback.
This works, but I can't access $_FILES in the same way which is possible if you use xhr.send().

By, the way, I'm aware this only works in modern browsers. I'm using Chrome.
I think your approach is flawed. You should use as much of Drupal's ajax system as possible, even though is wildly uncomprehensible and weird. Don't create your own Drupal.ajax object. Let Drupal handle that and the events and triggers that come with that.

Then there are only 2 problems left:


Don't create an iframe and a fake form and submit that. Use Ajax.
Don't serialize and preprocess that request. Use only what I'm giving you.


They're combined in jquery.form.js apparently. So all you have to do, is override where ajax.form.ajaxSubmit(ajax.options); is called: Drupal.ajax.prototype.eventResponse.

The result inside my failed-attempt-module.

It's an override of Drupal.ajax.prototype.eventResponse. I've added everything inside if ( 'FormData' in window )

My original plan (as the module name says) was to make all file fields drop containers for HTML5 File drag/drop. My approach was flawed too. I think with this approach, it's not so difficult. Just extend the FormData object at the right time.