18

Is it possible to check if by a given url the image exists and it's an image resource ?

for example:

angular.isImage('http://asd.com/asd/asd.jpg')

Or it's just a stuff for the server side ?

NO JQUERY please i'm not using it

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
itsme
  • 48,972
  • 96
  • 224
  • 345

2 Answers2

46

I think the best javascript approach would be to use HTMLImageElement object with deferred object:

function isImage(src) {

    var deferred = $q.defer();

    var image = new Image();
    image.onerror = function() {
        deferred.resolve(false);
    };
    image.onload = function() {
        deferred.resolve(true);
    };
    image.src = src;

    return deferred.promise;
}

Usage:

isImage('http://asd.com/asd/asd.jpg').then(function(test) {
    console.log(test);
});

Using HTMLImageElement gives you some benefits: not only it tests that the file is downloadable but also it is valid image resource that can be displayed by img tag.

I wrapped this code in simple service to make a test and it seems to work:

app.controller('MainCtrl', function($scope, Utils) {
    $scope.test = function() {
        Utils.isImage($scope.source).then(function(result) {
            $scope.result = result;
        });
    };
});

app.factory('Utils', function($q) {
    return {
        isImage: function(src) {
            // ... above code for isImage function
        }
    };
});

Demo: http://plnkr.co/edit/u5F6FfO3dEkNSMYV1amo?p=preview

dfsq
  • 191,768
  • 25
  • 236
  • 258
  • @dfsq You `isImage()` has a typo; in both `onerror` and `onload` you use `resolve()`. First one should be `reject()`. Apart from that, neat solution. – Thalis K. Aug 14 '15 at 13:13
  • @ThalisK. It's not a typo, I deliberately resolve (with `false` flag) in case of image unavailability, it doesn't feel to me like exceptional situation, so resolve is better. Plus for this functionality it would not be convenient to have both success and error handlers just in order to set proper flag `$scope.result = result;`. – dfsq Aug 14 '15 at 14:08
  • @dfsq True, in your case it doesn't make sense. I was misled by my application of your answer, where the promise rejection callback does different work from the success one and it was not being called. All clear. – Thalis K. Aug 14 '15 at 14:29
  • 1
    for those who don't know what the `$q` is, see: https://docs.angularjs.org/api/ng/service/$q – dsdsdsdsd Apr 10 '16 at 18:24
  • I believe this will cause a memory leak in chrome. Every image you check will create a new Image() object and this reference can hang around. See https://stackoverflow.com/questions/21309760/memory-leaks-when-manipulating-images-in-chrome?rq=1 – Clark Apr 15 '18 at 18:50
  • @Clark I don't think so, just made some tests and looks like memory is not leaking. – dfsq Apr 15 '18 at 21:15
9

You can use ng-src

<img ng-src="" />

Another way is you check if the it exists using the http module.

var app = angular.module('myapp', []).run(function($http){
  $http.get('http://asd.com/asd/asd.jpg',
    //success
    function(data){

    };
});

Update:

HTML

<div ng-controller="Ctrl">
       <img ng-src="{{src}}" isImage />
</div>

JS

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

app.directive('isImage', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('load', function() {
                alert('image is loaded');
            });
        }
    };
});

app.controller('Ctrl', function($scope) {
    $scope.src ="http://asd.com/asd/asd.jpg";
});
Thalaivar
  • 23,282
  • 5
  • 60
  • 71
  • sorry i forgot to specify i do not use jQuery :) i appriciate the same, thanks – itsme Mar 15 '14 at 11:24
  • @sbaaaang: I have also mentioned the Angular way using ng-src attribute and the other way is to check via server side which you have already mentioned in your thread – Thalaivar Mar 15 '14 at 11:25
  • i did not -1 , i gave you +1 actually, but please remove jquery part and if you can please specify how to use ng-src could be awesome !! thanks a lot – itsme Mar 15 '14 at 11:27
  • @sbaaaang: dfsq gave a better answer, i would have loved it if it was a directive. – Thalaivar Mar 15 '14 at 11:43
  • For those with the same problem, this is a cool answer using a directive. Tested works perfectly. http://stackoverflow.com/a/17122325/2689390 – jpgrassi Jul 16 '14 at 13:57