2

I have some API endpoints which provide images, but said images require authentication. I have a service (authenticatedHttp) which is an abstraction over $http and handles the authentication token management. (This is confirmed to be working, and for all intents and purposes might as well be $http)

I am receiving the response, getting a blob and creating an object URL. All of this works. I have checked the blob and can confirm it is correct.

The problem comes in when I try to apply objectUrl to src. I have tried a simplified example using a snippet I know works and no authentication. This does not work in my Angular app, but does work in vanilla JS.

I don't know much about ObjectUrl but if it makes a difference, when I inspect the empty image I see that it's src is correct, and that if I click the link created (ex. blob:https://sub.domain.dev/de4db0e0-77c8-44bc-a934-0d270ab81687) I get redirected by ui-router.

Why is this happening and how can I correct it?

app.directive('authenticatedSrc', ['authenticatedHttp', function (authenticatedHttp) {
  var directive = {
      link: link,
      restrict: 'A'
  };
  return directive;
  function link(scope, element, attrs) {
    var requestConfig = {
      cache: 'false'
    };
    authenticatedHttp.get(attrs.authenticatedSrc, requestConfig).then(function(response) {
      var objectUrl = window.URL.createObjectURL(new Blob([response.data], { type: 'image/png' }));
      attrs.$set('src', objectUrl);
    });
  }
}]);
9
  • Please for the future, if you want proper help, notice the tagging, angular-tag refers to angular <=2, you should have used angularjs. This time I fixed it for you ;) Commented Apr 14, 2017 at 20:03
  • 1
    @AJT_82 My bad, Thanks. Commented Apr 14, 2017 at 20:03
  • This tutorial will help developer.mozilla.org/en-US/docs/Web/API/FileReader/… Commented Apr 14, 2017 at 20:11
  • Object URLs point to objects that are local to the browser e.g. blob URLs data URLs. Remove blob: in the beginning of https. Commented Apr 14, 2017 at 20:17
  • @bhantol I tried that. I just get redirected by ui-router. Commented Apr 14, 2017 at 20:18

3 Answers 3

1

When downloading binary information, it is important to set the responseType:

app.directive('authenticatedSrc', ['authenticatedHttp', function (authenticatedHttp) {
  var directive = {
      link: link,
      restrict: 'A'
  };
  return directive;
  function link(scope, element, attrs) {
    var requestConfig = {
      //IMPORTANT
      responseType: 'blob',
      cache: 'false'
    };
    authenticatedHttp.get(attrs.authenticatedSrc, requestConfig).then(function(response) {
      //var objectUrl = window.URL.createObjectURL(new Blob([response.data], { type: 'image/png' }));
      var blob = response.data;
      attrs.$set('src', blob);
    });
  }
}]);

Otherwise the data gets corrupted by conversion from UTF-8 to DOMstring (UTF-16).

For more information, see MDN XHR API ResponseType.

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

Comments

1

@Kaiido was correct also, but it was not my main problem.

@georgeawg solved the majority of my problem, but I did not accept his answer because his implementation (using the blob directly as the source) did not work for me.

This is my final code which works.

app.directive('authenticatedSrc', ['authenticatedHttp', function (authenticatedHttp) {
  var directive = {
      link: link,
      restrict: 'A'
  };
  return directive;
  function link(scope, element, attrs) {
    var requestConfig = {
      cache: 'false',
      responseType: 'blob'
    };
    authenticatedHttp.get(attrs.authenticatedSrc, requestConfig).then(function(response) {
      var reader = new window.FileReader();
      reader.readAsDataURL(response.data);
      reader.onloadend = function() {
        attrs.$set('src', reader.result);
      };
    });
  }
}]);

Comments

0

What is the return type of response.data? Is it a base64 encoded string? Img tag can very well render base64 encoded images when provided directly in the src attribute. Moreover, please try $sce service of angularjs to trust this objectUrl as a valid Url. $sce.trustAsURL(objectUrl) while adding to src attribute. More info https://docs.angularjs.org/api/ng/service/$sce

3 Comments

It's binary. But Postman displays it just fine. I've converted to base64 and tried it that way, but that didn't seem to work either.
Please give a shot a $sce and check if it renders the image. Do you see empty box or a image not found icon?
Yes. It displays the "image not found".

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.