John B.
John B.

Reputation: 2359

Simulate XHR2 file upload

I have a HTML upload button to send (multiple) files to a server which responds with JSON. Based on that response, my application flow continues.

Now, to test the rest of my code (dependent on the server response), I would like to simulate the file upload so that I do not have to manually select and upload new files on every reload.

Following is a simplified version of my upload method:

uploadToServer: function (file) {

    var self = this,
        data = new FormData(),
        xhr = new XMLHttpRequest();

    // When the request has successfully completed.
    xhr.onload = function () {
        var response = $.parseJSON(this.responseText);

        var photo = new App.Models.Photo({
            filename: response.filename,
            name: response.uuid
        });

        var photoView = new App.Views.Photo({ model: photo });

        $('.photos').append(photoView.render().el);
    };

    // Send to server, where we can then access it with $_FILES['file].
    data.append('file', file);
    xhr.open('POST', this.url);
    xhr.send(data);
}

The uploadToServer parameter file is a File-object from FileList. And as you can see, my server awaits the file inside of $_FILES['file'].

It would be awesome if a could simulate a real File-object being passed into uploadToServer, since I then do not have to worry about my existing events such as xhr.onload and xhr.onprogress being available.

If that won't be possible, I could create a custom uploadToServer method and send a regular AJAX-request and fake-respond on my server. But how can I then use and bind the code from my events (xhr.onload, xhr.onprogress etc.) to that AJAX-request?

Upvotes: 1

Views: 1889

Answers (1)

nikoshr
nikoshr

Reputation: 33344

You could simulate a file upload by creating a canvas, converting it to a file and passing the result to your method.

  1. Create a canvas : here, a nice red square

    var canvas = document.createElement('canvas'),
        ctx = canvas.getContext("2d");
    
    canvas.width = 100;
    canvas.height = 100;
    ctx.fillStyle = '#ff0000';
    ctx.fillRect(0, 0, 100, 100);
    
    document.body.appendChild(canvas);
    
  2. Convert it to a file and pass it to your method: I used Canvas to Blob to simplify the test but you probably can extract the bare bones to fit your needs.

    canvas.toBlob( function (blob) {
        m.uploadToServer(blob);
    }, 'image/jpeg');
    

And a Fiddle http://jsfiddle.net/pvWxx/ Be sure to open a console to see the events and the request.

If you want to pass a filename with your blob, you can pass a third argument to formData.append, see How to give a Blob uploaded as FormData a file name? and an updated Fiddle http://jsfiddle.net/pvWxx/1/

Upvotes: 2

Related Questions