10

Working with HTML5's File API, the upload is made via an object called upload in the XMLHttpRequest. This is the tutorial I'm working with (and the Google cache mirror since it's down at the moment). This is the relevant part:

// Uploading - for Firefox, Google Chrome and Safari
xhr = new XMLHttpRequest();

// Update progress bar
xhr.upload.addEventListener("progress", function (evt) {

As you can see, to track the upload progress, the XMLHttpRequest object has a property named upload, which we can add an event handler.

My question is: has jQuery an equivalent?. I'm attempting to leave the code as clean as and cross-browser compatible as possible, for whenever Microsoft thinks it's a good idea (although it sounds like it will be in 2012 or 2013).

thirtydot
  • 224,678
  • 48
  • 389
  • 349
metrobalderas
  • 5,180
  • 7
  • 40
  • 47
  • Are you looking for a jQuery plugin or to find out if the jQuery XHR wrapper supports this functionality? – justkt Mar 01 '11 at 16:46
  • @justkt I'm looking for a built-in option in jQuery, altough, if not available, a plugin will be nice. Thanks. – metrobalderas Mar 01 '11 at 16:52
  • 3
    If you're working with HTML5 already, you're not seriously considering cross browser compatibility so just build for what does work and have a message telling people to use one of the working browsers. The same goes for CSS3. – Endophage Mar 01 '11 at 16:52
  • IE9 has both XMLHttpRequest support and the addEventListener method. I think you should just test if `xhr.upload` exists and be done with it. No need to wrap your code with jQuery. – gonchuki Mar 01 '11 at 16:56
  • 1
    @Endophage Ok, thanks for your comment. And of course, I've got a fallback. – metrobalderas Mar 01 '11 at 16:56
  • @gonchuki, yes, I'm well aware of this. But what I'm looking for is a way to let jQuery create the `XMLHttpRequest` object for me and handle all the rest. – metrobalderas Mar 01 '11 at 17:00

2 Answers2

17

Here is what I came up with to get around the issue. The $.ajax() call allows to provide a callback to generate the XHR. I just generate one before calling the request, set it up and then create a closure to return it when $.ajax() will need it. It would have been much easier if they just gave access to it through jqxhr, but they don't.

var reader = new FileReader();

reader.onloadend = function (e) {
    var xhr, provider;

    xhr = jQuery.ajaxSettings.xhr();
    if (xhr.upload) {
        xhr.upload.addEventListener('progress', function (e) {
            // ...
        }, false);
    }   
    provider = function () {
        return xhr;
    };  

    // Leave only the actual base64 component of the 'URL'
    // Sending as binary ends up mangling the data somehow
    // base64_decode() on the PHP side will return the valid file.
    var data = e.target.result;
    data = data.substr(data.indexOf('base64') + 7); 

    $.ajax({
        type: 'POST',
        url: 'http://example.com/upload.php',
        xhr: provider,
        dataType: 'json',
        success: function (data) {
            // ...
        },  
        error: function () {
            // ...
        },  
        data: {
            name: file.name,
            size: file.size,
            type: file.type,
            data: data,
        }   
    }); 
};  
reader.readAsDataURL(file);
Louis-Philippe Huberdeau
  • 5,341
  • 1
  • 19
  • 22
  • That's a great answer, but having to send the base64 encoded as a data param feels a little wrong.. however it's a very creative solution while it's not on the jQuery core. – metrobalderas Jun 15 '11 at 18:58
  • 1
    Binary strings are not kept -> This behaviour can be conducted from the specification, as explained [in this answer](http://stackoverflow.com/a/10073841/938089?xmlhttprequest-multipart-related-post-with-xml-and-image-as-payload). The `XMLHttpRequest.prototype.sendAsBinary` method is covered [here](http://stackoverflow.com/a/9250818/938089). In jQuery, override the `.send` method using the previous answer, via the `xhr` setting (see [this answer](http://stackoverflow.com/q/4303448?how-to-override-jquerys-use-of-xmlhttprequest-in-ajax)). – Rob W Jun 07 '12 at 08:04
2

The documentation for the jqXHR (the superset of the XMLHttpRequest that is returned from jQuery's .ajax() call) does not describe the update feature as being exposed, which does not mean it isn't exposed. This question, though, seems to indicate that upload is not exposed. The answer provides a way to get to the native XMLHttpRequest object.

In versions before jQuery 1.5 the XMLHttpRequest object was exposed directly, and so you can access any feature of it that the browser supports. This tutorial for building a drag and drop uploader does just that.

A search for jquery html 5 file upload brings up this plugin to do multiple file upload using the HTML 5 file API, but this plugin does not currently work in IE. If you don't want to use HTML 5 and instead do want to have support cross-browser now, there are other plugins you can look into for jQuery on the jQuery plugin site.

Community
  • 1
  • 1
justkt
  • 14,610
  • 8
  • 42
  • 62