Using the FormData interface

One of the new features added to XMLHttpRequest Level 2 (http://www.w3.org/TR/XMLHttpRequest2/) is the FormData object. This enables us to use a set of key-value pairs that can be sent using AJAX. The most common use is in sending binary files or any other large amount of data. In this recipe, we will create two scripts that will send FormData, one with a plain JavaScript and the other with jQuery, as well as the server-side code to support it.

Getting ready

The server will be done in Nodejs using restify (http://mcavage.github.io/node-restify/). In order to install the dependencies, a package.json file can be created where restify will be added.

How to do it...

  1. The server should be able to accept HTTP POST with type multipart/form-data; that is why there is a built-in plugin for restify called BodyParser. This will block the parsing of the HTTP request body:
    var server = restify.createServer();
    server.use(restify.bodyParser({ mapParams: false }));
    server.post('hi', addHeaders, doPost);
  2. This switches the content type, and depending on it, does the appropriate logic for application/json, application/x-ww-form-urlencoded, and mutipart/form-data. The addHeaders parameter will be the same as we added in the other examples that enables CORS. For simplicity in our doPost handler, we just log the request body and return HTTP 200:
    function doPost(req, res, next) {
      console.log("Got HTTP " + req.method + " on " + req.url + " responding");
      console.log(req.body);
      res.send(200);
      return next();
    }
  3. For the client side, we create an HTML file that will have a simple script:
    (function (){
    var myForm = new FormData();
    myForm.append("username", "johndoe");
    myForm.append("books", 7);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "http://localhost:8080/hi");
    xhr.send(myForm);
      }());
  4. The jQuery way is a lot simpler; we can set FormData as part of the data attribute in jQuery.ajax() where additionally we need to disable data processing before we send and leave the original content type:
    (function(){
      var formData = new FormData();
      formData.append("text", "some strange data");
      $.ajax({
        url: "http://localhost:8080/hi",
        type: "POST",
        data: formData,
        processData: false,  // don't process data
        contentType: false   // don't set contentType
      });
    }());

How it works...

The transmitted data will have the same format as it would if we submitted a form that has the multipart/form-data encoding type. The need for this type of encoding comes from sending mixed data together with files. This encoding is supported by most of the web browsers and web servers. The encoding can be used for forms that are not HTML or even part of the browser.

If we take a look at request being sent, we can see that it has the following data:

Content-Length:239
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryQXGzNXa82frwui6S

The payload will be as follows:

------WebKitFormBoundaryQXGzNXa82frwui6S
Content-Disposition: form-data; name="username"
johndoe
------WebKitFormBoundaryQXGzNXa82frwui6S
Content-Disposition: form-data; name="books"
7
------WebKitFormBoundaryQXGzNXa82frwui6S--

You may notice that each of these parts contain a Content-Disposition section with the name of the control that is an origin of the data or, in our case, the key we set in every append to the FormData object. There is also an option to set the content type on each individual part, for example, if we had an image from some control named profileImage then that part can be as follows:

Content-Disposition: form-data; name="profileImage"; filename="me.png"
Content-Type: image/png

The last call to xhr.sent() in example.js sets the content type automatically when we are sending an object of type FormData.

And if we need to support older legacy browsers that don't have XMLHttpRequest level 2, we can check if FormData is there and handle that case accordingly:

if (typeof FormData === "undefined")

The method we use as a fallback cannot be an AJAX call, but this should not be a problem as all the modern browsers IE<10 version don't have support for it.

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

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