Reputation: 2015
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);
});
}
}]);
Upvotes: 2
Views: 1685
Reputation: 2015
@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);
};
});
}
}]);
Upvotes: 1
Reputation: 48968
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.
Upvotes: 1
Reputation: 11
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
Upvotes: 0