1

So I am trying to check if an image URL is valid or not, in which it has to return a true or false value. The problem is that I can't figure out how to achieve this. I'm using ionic 4.0 and this is what I already have:

imageExists(url, callback) {
   const img = new Image();
   img.onload = function () { callback(true); };
   img.onerror = function () { callback(false); };
   if(callback === true ) {
     return true;
    } else {
      return false;
    }
}

  const imageUrl = 'https://www.google.com/images/srpr/nav_logo14.png';
  let bool = this.imageExists(imageUrl, function (exists) {
    console.log('RESULT: url=' + imageUrl + ', exists=' + exists);
    console.log(exists);
    bool = exists;
  });


console.log(bool);
norbitrial
  • 14,716
  • 7
  • 32
  • 59
Cleax
  • 31
  • 5
  • `callback` argument is being passed a function. `imageExists` will always be false – danronmoon Oct 07 '19 at 19:46
  • Maybe relevant as image loading is an async operation: https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call?noredirect=1&lq=1 – danronmoon Oct 07 '19 at 19:47

4 Answers4

0

You're close, but you need to set img.src = url to start it trying to load :) Also, remove the check for if (callback === true) as that doesn't make sense; callback is a function, not a boolean. The boolean value gets passed TO the function as an argument in the onload / onerror handlers.

IceMetalPunk
  • 5,476
  • 3
  • 19
  • 26
0

You could use some regex to achieve this.

function validURL(str) {
  var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
    '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
    '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
    '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
    '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
    '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
  return !!pattern.test(str);
}

Source : Check if a JavaScript string is a URL

David Thomas
  • 249,100
  • 51
  • 377
  • 410
Trisma
  • 735
  • 6
  • 19
  • 1
    That - with the usual regexp edge-cases, provisos and caveats - may be a means to test for a potentially-valid URL, but it doesn’t verify whether an image is returned from that URL. – David Thomas Oct 07 '19 at 20:07
  • looks like this solves my problem, but i don't understand why it works. could you explain what's happening here? – Cleax Oct 07 '19 at 20:12
  • You can go to this site : https://regex101.com/ this will give you a detailed explanatio about regex – Trisma Oct 09 '19 at 07:48
  • @DavidThomas it indeed don't check if the URL links to an image, but the question was to see if the URL is valid if I understand well, otherwise there should be some checks after that regex expression to see if the output is actually an image. – Trisma Oct 14 '19 at 10:56
  • Perhaps, my comment was based on an inference from the apparent functionality of the code in the question, rather than strictly reading the question. – David Thomas Oct 14 '19 at 16:27
0

Well you can actually do that by testing if the image resolves to something how about this

    function imageResolves(image_url){

    var request = new XMLHttpRequest();
    try {
      request.open('HEAD', image_url, false);
      request.send();
    } catch(error){
      return false;
    }
     return request.status === 200;

}

Or using a similar option as the one you proposed with:

function imageExists(imageSrc) {

    return new Promise(function(resolve,reject){
      var img = new Image();
      img.src = imageSrc;
      img.onload = resolve;
      img.onerror = reject;
        })
}

And then to use it you would do something like

imageExists('https://www.google.com/images/srpr/nav_logo14.png').then(function(){
//It exists
},function(){
//It does not exist
})

Here is a jsFiddle with both implementations https://jsfiddle.net/sudakatux/s19oL5zg/7/

Notice that with the first option you may get CORS issues depending on the headers

jstuartmilne
  • 4,398
  • 1
  • 20
  • 30
0

What about checking by fetching the image itself, a valid url actually is not a real image, the way you can do that, maybe by doing this

const contentTypePart = "image";
const isImage = (url) => new Promise((resolve, reject) => {
  // check that is a valid url
  // then if valid url
  fetch(url).then((response) => {
    if (response.ok) {
      const currentContentType = response.headers.get('Content-Type');
      // check if the content type is actually an image extension
      if (currentContentType.indexOf(contentTypePart) > -1) {
        return resolve(url);
      }
    }
    reject(false);
  }).catch(reject)
})

or if you prefer using the Image constructor

const contentTypePart = "image";
const isImage = (url) => new Promise((resolve, reject) => {
  // check that is a valid url
  // then if valid url
  const image = new Image();
  image.src = url;
  image.onload = resolve;
  image.onerror = reject;
});

Finally the way to use it is

isImage('https://www.google.com/').then(console.log.bind(null, 'is a valid image')).catch(console.error.bind(null, 'is not a valid image'))

the code above will throw a console.error because the url is a website not an image.

by doing this, you can check that the url is actually a real and valid image.

Juorder Gonzalez
  • 1,642
  • 1
  • 8
  • 10