Posting a binary file to the server

Posting text, XML, or JSON to the server is relatively easy, and most JavaScript libraries are optimized for that scenario.

Posting binary data is slightly trickier. Modern applications may need to be able to upload the generated binary files; examples include images drawn on an HTML5 canvas, ZIP files created with JSZip, and so on.

Additionally, it's convenient to be able to upload files selected using the HTML5 file API. We can do some interesting things with it, such as resumable file uploads by splitting the file into smaller parts and uploading every part separately to the server.

In this recipe, we're going to upload files selected by the user using a file input.

Getting ready

The server will be implemented using Node.js—you can download and install Node.js from http://nodejs.org/. The server will be implemented with the Node.js framework Connec t (http://www.senchalabs.org/connect/).

How to do it...

Let's write the client and server code.

  1. Create a file named index.html—the file upload page that includes a file input, upload button, a progress bar, and a message container:
    <!DOCTYPE HTML>
    <html>
    <head>
    <title>Upload binary file</title>
    <style type="text/css">
    .progress {
        position:relative;
        height:1em; width: 12em;
        border: solid 1px #aaa;
    }
    .progress div {
        position: absolute;
        top:0; bottom:0; left:0;
        background-color:#336699;
    }
    </style>
    </head>
    <body>
    <input type="file"   id="file" value="Choose file">
    <input type="button" id="upload" value="Upload"><br>
    <p id="info"></p>
    <div class="progress"><div id="progress"></div></div>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script type="text/javascript" src="uploader.js"></script>
    <script type="text/javascript" src="example.js"></script>
    </body>
    </html>
  2. Create a file named uploader.js that implements a binary file uploader. It posts the file to a specified URL and returns an object that enables the binding of progress events:
    window.postBinary = function(url, data) {
        var self = {},
            xhr = new XMLHttpRequest();
        xhr.open('POST', url, true);
        xhr.responseType = 'text';    
        self.done = function(cb) {
            xhr.addEventListener('load', function() {
                if (this.status == 200)
                    cb(null, this.response)
                else
                    cb(this.status, this.response)
            });
            return self;
        }
        self.progress = function(cb) {
            xhr.upload.addEventListener('progress', function(e) {
                if (e.lengthComputable) 
                    cb(null, e.loaded / e.total);
                else
                    cb('Progress not available'),
            });
            return progress;
        };
        xhr.send(data);    
        return self;
    };
  3. Create a file named example.js that uses the API provided by uploader.js to add the upload functionality to the upload form:
    $(function() {
        var file;
        $("#file").on('change', function(e) {
            file = this.files[0]
        });
        $("#upload").on('click', function() {
            $("#info").text("Uploading...");
            $("#progress").css({width:0});
            if (!file) {
                $("#info").text('No file selected')
                return;
            }
            var upload =  postBinary('/upload/' + file.name, file);
            upload.progress(function(err, percent) {
                if (err) {
                    $("#info").text(err);
                    return;
                }
                $("#progress").css({width: percent + '%'});
            });
            upload.done(function(err, res) {
                if (err) {
                    $("#info").text(err + ' ' + res);
                    return;
                }
                $("#progress").css({width: '100%'});
                $("#info").text("Upload complete");
            });
    
        });
    });
  4. Create a file named server.js—a Node.js server based on the Node.js Connect framework that handles the file uploads and serves the static files:
    var path = require('path'),
        connect = require('connect'),
        fs = require('fs'),
    
    connect()
        .use('/upload', function(req, res) {        
            var file = fs.createWriteStream(
                path.join(__dirname, 'uploads', req.url))
            req.pipe(file);
            req.on('end', function() {
                res.end("ok");
            });
        })
        .use(connect.static(__dirname))
        .listen(8080);
  5. Open a command prompt from the directory where server.js is located and type the following commands to create a directory for the uploads, install the connect library, and start the server:
    mkdir uploads
    npm install connect
    node server.js
    
  6. Navigate your browser to http://localhost:8080 to test the example. All the created files (including server.js) should be in the same directory.

How it works...

The new XMLHttpRequest object in HTML5 has a send method that supports more types of data. It can accept File, Blob, and ArrayBuffer objects. We use this new functionality together with the HTML5 File API to upload the file selected by the user. You can find out more about this API in the Using file inputs on the client side recipe of Chapter 4, Using HTML5 Input Components.

The new API also provides an upload object, which is of type XMLHttpRequestUpload. It allows us to attach event listeners to monitor the upload progress. We use this functionality to show a progress bar for the upload.

The server accepts the uploads at '/upload' and saves the files to the uploads directory. Additionally, it serves the static files in the example directory.

There's more…

The new XHR API is only available in Internet Explorer 10 and up.

Some browsers may fail to fire upload progress events.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.93.0