Saturday, 2 November 2013

Reading Binary Data with the File API and JavaScript

As part of a series of articles I am discussing some of the challenges I faced when trying to build a HTML5 and JavaScript free online icons editor.

I wanted users to be able to open and edit existing icon files in my icon editor. As icon files can contain multiple frames, I needed to access these individual frames so they can be displayed and be available to edit for the user. The number, size and location of frames contained within an icon is all stored in the icon header. The icon header is a collection bytes located at the start of an icon file so I needed to read the binary data contained in the file.

We can now read files easily in the browser without having to send any data back to a server. In this installment I show how you can read binary data of a local file in the browser using the HTML5 File API.

To start with we're going to add an input element and set the type attribute to "file", then in a script block we are going to handle the file input's onchange event.

  1. <body>                            
  2.     <input id="browseOpen" type="file"/>
  3.  
  4.     <script type="text/javascript">
  5.         var fileInput = document.getElementById("browseOpen");
  6.         fileInput.onchange = function () {
  7.             // Code to handle onchange event goes here
  8.         };
  9.     </script>
  10. </body>

Now we need to add the code to handle the onchange event. In here we are going to create a FileReader object. We will use the readAsBinaryString method of the FileReader object which will give us the raw binary data. We can pass a File object to the readAsBinaryString if we want to read the whole file or we can pass a Blob object if we just want to read a certain section of a file. In this example we are going to pass a File object to read the whole file. We also need to handle the onloadend event of the FileReader as the data we read with readAsBinaryString is only available to use once the whole file or blob has been read by the FileReader. Our code in the onchange event handler now looks like this.

  1.         var fr = new FileReader();
  2.         fr.onloadend = function () {
  3.             // Code to handle onloadend event
  4.         };
  5.         fr.readAsBinaryString(this.files[0]);

In the onloadend event handler we can access the data that has just been read via the FileReader's result attribute. We can then loop through the result attribute and call the charCodeAt method to return an integer value of each byte. In this example I'm going to convert the byte to a hexadecimal string representation using toString(16), build up one long string and then display the string to the user. Here's the full working example.

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4.     <title>Reading Binary Data with the File API and JavaScript</title>
  5. </head>
  6. <body>                            
  7.     <input id="browseOpen" type="file"/>
  8.  
  9.     <script type="text/javascript">
  10.         var fileInput = document.getElementById("browseOpen");
  11.         fileInput.onchange = function () {            
  12.             var fr = new FileReader();
  13.             fr.onloadend = function () {
  14.                 var result = this.result;
  15.                 var hex = "";
  16.                 for (var i = 0; i < this.result.length; i++) {
  17.                     var byteStr = result.charCodeAt(i).toString(16);
  18.                     if (byteStr.length < 2) {
  19.                         byteStr = "0" + byteStr;
  20.                     }
  21.                     hex += " " + byteStr;
  22.                 }
  23.                 alert(hex);
  24.             };
  25.             fr.readAsBinaryString(this.files[0]);
  26.         };
  27.     </script>
  28. </body>
  29. </html>

No comments:

Post a comment