4

I would like to extract binary data from a binary file into a byte array. I am having difficulty getting it to work correctly.

You can see the jsFiddle here: https://jsfiddle.net/alexsuch/6aG4x/

The HTML:

<div ng-controller="MainCtrl" class="container">
  <h1>Select text file</h1>
    <input type="file" on-read-file="showContent($fileContent)" />
    <div ng-if="content">
        <h2>File content is:</h2>
        <pre>{{ content }}</pre>
    </div>
</div>

The Javascript code:

var myapp = angular.module('myapp', []);

myapp.controller('MainCtrl', function ($scope) {
    $scope.showContent = function($fileContent) {
        $scope.content = $fileContent;
    };
});

myapp.directive('onReadFile', function ($parse) {
    return {
        restrict: 'A',
        scope: false,
        link: function(scope, element, attrs) {
            var fn = $parse(attrs.onReadFile);

            element.on('change', function(onChangeEvent) {
                var reader = new FileReader();

                reader.onload = function(onLoadEvent) {
                    scope.$apply(function() {
                        fn(scope, {$fileContent:onLoadEvent.target.result});
                    });
                };

                reader.readAsText((onChangeEvent.srcElement || onChangeEvent.target).files[0]);
            });
        }
    };
});

I get a corrupted text format as shown in this: enter image description here

What am I doing wrong that's causing the content to be garbled like this?

Ilyas Berhail
  • 43
  • 1
  • 5
  • Would you like to display or save the file? Do you know in what format the file was send, buffer / base64? – chenop Jun 10 '16 at 12:44
  • Maybe this one can help you: http://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript – chenop Jun 10 '16 at 12:46
  • What do you want to show to the user ? Binary files is a binary files, do you want to show them the bytes value ? If so then you should use a function to convert your array of bytes to an hexadecimal string – Walfrat Jun 10 '16 at 12:49
  • Actually i want to get the file content and put it in JSON object and store it in mongoDB document. – Ilyas Berhail Jun 10 '16 at 12:54
  • The file that i would to sent has a buffer format and not a base64 – Ilyas Berhail Jun 10 '16 at 12:56
  • The file you uploaded is not plain text, thus seems like corrupted. if you upload a plain file (txt, .html etc) you can see that it works well. – emrhzc Jun 10 '16 at 12:59
  • yeah it works pefectely – Ilyas Berhail Jun 10 '16 at 13:35

1 Answers1

6

You say you want the file's binary content to send over JSON and store in mongoDB. The problem with your code is that you're reading the file as text, when you should be reading it as an ArrayBuffer, which won't apply text encoding to the binary values.

ArrayBuffer is great, but not all browsers will support sending ArrayBuffer over JSON via XMLHttpRequest. Especially if you know the format it needs to be in, it might be a good idea to convert it to a regular array. Luckily, we can use typed arrays in JavaScript to help that.

var myapp = angular.module('myapp', []);

myapp.controller('MainCtrl', function ($scope) {
    $scope.showContent = function($fileContent) {
        $scope.content = $fileContent;
    };
});

myapp.directive('onReadFile', function ($parse) {
    return {
        restrict: 'A',
        scope: false,
        link: function(scope, element, attrs) {
            var fn = $parse(attrs.onReadFile);

            element.on('change', function(onChangeEvent) {
                var reader = new FileReader();

                reader.onload = function(onLoadEvent) {
                    var buffer = onLoadEvent.target.result;
                    var uint8 = new Uint8Array(buffer); // Assuming the binary format should be read in unsigned 8-byte chunks
                    // If you're on ES6 or polyfilling
                    // var result = Array.from(uint8);
                    // Otherwise, good old loop
                    var result = [];
                    for (var i = 0; i < uint8.length; i++) {
                      result.push(uint8[i]);
                    }

                    // Result is an array of numbers, each number representing one byte (from 0-255)
                    // On your backend, you can construct a buffer from an array of integers with the same uint8 format
                    scope.$apply(function() {
                        fn(scope, {
                          $fileContent: result
                        });
                    });
                };

                reader.readAsArrayBuffer((onChangeEvent.srcElement || onChangeEvent.target).files[0]);
            });
        }
    };
});

Updated fiddle: https://jsfiddle.net/6aG4x/796/

hotforfeature
  • 2,558
  • 1
  • 16
  • 24