23

In my controller I call a service that returns a promise

var onComplete = function(data) {
               $scope.myImage = data;           
            };

In my service I make a call to get the image by passing url directly to the image itself:

   return $http.get("http://someurl.com/someimagepath")
         .then(function(response){          
          return response.data;
         });

All the calls are succeeding and the response.data appears to be holding in an image inside:

����JFIF��;CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), quality = 90
��C




��C      

����"�� 
���}!1AQa"q2���#B��R��$

although I'm not sure if it actually does because I'm having trouble displaying it. I've tried (inside index.html)

 <img ng-src="{{myImage}}"> 
  and
<img ng-src="{{myImage}}.jpeg"> 
  and   
 <img ng-src="data:image/JPEG;base64,{{myImage}}">

Ideas? Is it possible to return an actual image from $http.get and convert its response back to image (jpeg, etc.)

Thanks!

5
  • Based on my experiments with trying to inject images into tags in order to reduce HTTP requests for a single-page angular app I was making, no, it isn't possible. Commented Apr 21, 2015 at 18:20
  • 1
    What's the end goal here? If you know http://someurl.com/someimagepath, why do you need to download it via an $http.get() and then inject it into an src tag when you can skip the middle man and simply put the path in the src tag? Commented Apr 21, 2015 at 18:22
  • 1
    @Tom - it was just a test to retrieve some data asynchronously and I thought of retrieving an image with it. No real end goal other than learning AngularJS Commented Apr 21, 2015 at 18:24
  • Could you check this question, I'm having similar problems : stackoverflow.com/questions/47161442/… Commented Nov 8, 2017 at 12:17
  • this answer actually worked for me stackoverflow.com/a/33125433/4631539 Commented Nov 14, 2017 at 6:33

4 Answers 4

37

None of the methods seems to be complete, this is a complete solution:

  $http({
    method: 'GET',
    url: imageUrl,
    responseType: 'arraybuffer'
  }).then(function(response) {
    console.log(response);
    var str = _arrayBufferToBase64(response.data);
    console.log(str);
    // str is base64 encoded.
  }, function(response) {
    console.error('error in getting static img.');
  });


  function _arrayBufferToBase64(buffer) {
    var binary = '';
    var bytes = new Uint8Array(buffer);
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
      binary += String.fromCharCode(bytes[i]);
    }
    return window.btoa(binary);
  }

Then I am able to use it directly:

<img data-ng-src="data:image/png;base64,{{img}}">

The function to convert arraybuffer into base64 is directly taken from ArrayBuffer to base64 encoded string

Sign up to request clarification or add additional context in comments.

3 Comments

The scenario of this post matches my situation closely. I like the potential of this solution, but unfortunately does not like the structure or format of the binary data (byte array) that is being passed back via Angular's $http service. The Uint8Array comes back empty when trying to create the array of bytes. I'll post my solution once I discern the difference.
You saved my day..!! Thank you. @paradite can i know how to retreive list of images and display
Worked!! Somebody give this guy a medal!!. Also to the future readers the responseType: 'arraybuffer' in $http is important please do not miss it. I was trying to get it done without it but couldn't. Without this the _arrayBufferToBase64 seems to return empty string.
18

Just in case anyone needs it.

In my case, I had to send the request through angular's $http service, because of various transformers and other fancy stuff we do with it.

So based on the Mozilla's guide mentioned earlier, I came up with the following solution:

let getImageDataURL = (url, imageType = 'image/jpeg') => {
  return $http.get(url, {responseType: 'arraybuffer'}).then((res) => {
    let blob = new Blob([res.data], {type: imageType});
    return (window.URL || window.webkitURL).createObjectURL(blob);
  });
};

The basic idea is to set the responseType property of the underlying XHR request and the convert the binary content to data URL.

Comments

7

The image that's coming back is in binary encoding, rather than Base64.

Understandably, <img> tags don't support sourcing from binary through attributes, so you'll have to look at another solution.

You could try converting the binary encoding to Base64 at the client side using TypedArrays together with the btoa function. Then you'd be able to use

<img ng-src="data:image/JPEG;base64,{{myImage}}">

This guide a by Mozilla covers making an XHR request for and image and reading it directly into a UInt8Array. It should be a good starting place.

It's written for plain old Javascript, but translating it to Angular should be a good exercise if you are just learning the ropes.

4 Comments

Thanks, it does look like a binary string. I'll check out the guides!
@ra170 Could you post the code for this if you managed to solve it?
@Tometoyou found the solution by googling around arraybuffer to base64: stackoverflow.com/questions/6965107/…
Could you check this question, I'm having similar problems : stackoverflow.com/questions/47161442/…
1

By way of https://stackoverflow.com/a/43032560/418819, you can use "blob" as the responseType and very neatly get the data url with a FileReader.

$http.get( url, { responseType: "blob" } ).then((result) => {
  var reader = new FileReader();
  reader.readAsDataURL( result.data );
  reader.onload = function (e) {
    return e.target.result;
  };
});

You can reference it like so:

<img data-ng-src="{{img}}">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.