37

In AngularJS there is the $http.get to dynamically fetch data. Unfortunately, from the official doc is not easy to understand how to read binary data (for example, for image manipulation).

The default get fetches the data as a String (see it in a plunker). This is very cumbersome. So, how to get it in an ArrayBuffer? (Note that since XHR2 this is already possible.)

<!DOCTYPE html>
<html>
  <head>
    <title>Using $http.get to read binary data</title>
  </head>
  <body ng-app>
    <h1>$http to load binary data</h1>
    <div ng-controller="FetchCtrl" >
      <button ng-click="fetch()">fetch</button><br/>
      {{info}}
    </div>
    <script src="http://code.angularjs.org/1.0.6/angular.min.js"></script>
    <script>
    // Controller
    function FetchCtrl($scope, $http) {
      // See note 1
      $scope.URL = "http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png";
      $scope.info = "Click 'fetch' to fetch an image" ;

      $scope.fetch = function() {
        delete $http.defaults.headers.common['X-Requested-With']; // See note 2
        $http.get($scope.URL).
          success(function(data) {
            $scope.info = "Read '" + $scope.URL + "' with " + data.length
            + " chars in a variable of type '" + typeof(data) + "'";
          }).error(function(data, status) {
            $scope.info = "Request failed with status: " + status;
          });
      };
    }      
    </script>
  </body>
</html>

Note 1: The size of the original file is 473.831 bytes.
Note 2: If the image to fetch belongs to a different domain, resetting headers could be necessary to perform a simple cross-site request: By default, AngularJS 1.0.6 sets the X-Requested-With: XMLHttpRequest header, forcing a preflighted request, that is, the browser sends an http OPTIONS request before the GET. This could be not supported by the server (like in this example, where the server returns a 403 HTTP method not allowed).
This header was removed six months ago though, (that is, from AngularJS 1.1.1 on), and the reset is not necessary anymore (thanks by the way to this answer to AngularJS performs an OPTIONS HTTP request for a cross-origin resource).

Community
  • 1
  • 1
Alberto
  • 4,651
  • 3
  • 38
  • 64

1 Answers1

54

Fortunately, Vojta Jina has already implemented this feature in branch 1.1. The following code (see it in a plunker) fetches the binary data in an ArrayBuffer. Note the use of the (as for today) still unstable AngularJS 1.1.5:

<!DOCTYPE html>
<html>
  <head>
    <title>Using $http.get to read binary data</title>
  </head>
  <body ng-app>
    <h1>Using $http.get to read binary data</h1>
    <div ng-controller="FetchCtrl" >
      <button ng-click="fetch()">fetch</button><br/>
      {{info}}
    </div>
    <script src="http://code.angularjs.org/1.1.5/angular.min.js"></script>
    <script>
    // Controller
    function FetchCtrl($scope, $http) {
      // See note 1
      $scope.URL = "http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png";
      $scope.info = "Click 'fetch' to fetch an image" ;
      $scope.fetch = function() {
        delete $http.defaults.headers.common['X-Requested-With']; // See note 2
        $http.get($scope.URL, {responseType: "arraybuffer"}).
          success(function(data) {
            $scope.info = "Read '" + $scope.URL + "' with " + data.byteLength
            + " bytes in a variable of type '" + typeof(data) + "'";
          }).
          error(function(data, status) {
            $scope.info = "Request failed with status: " + status;
          });
      };
    }      
    </script>
  </body>
</html>

Note 1 and note 2: see notes in the original question.

Alberto
  • 4,651
  • 3
  • 38
  • 64