cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Visit the PTCooler (the community lounge) to get to know your fellow community members and check out some of Dale's Friday Humor posts! X

Check if image exists

Wes_Tomer
13-Aquamarine

Check if image exists

Hello,

I would like to check if app/resources/IMAGES/Filename.JPG exists or not, and then display scrolling arrows (left and right) if multiple images exist. I can figure out the scrolling arrows, and how to change the 3D image widget, but I can't find a way to check if JPG files are uploaded. I display a different image for each step of an animation, but some steps will have multiple images associated with them.

 

I have tried Stack Overflow: Check synchronously if file/directory exists in Node.js

but I get the error in my console "TypeError: Cannot read property 'access' of undefined"

 

var name = // code I use to concatenate a filename string ending in .jpg
var p = "app/resources/IMAGES/"+name;
        fs.access(p, error => {
          if (!error) {
              console.log("exists: "+p);
          } else {
              console.log("does not exist: "+p);
          }

Any suggestions?

Thanks

ACCEPTED SOLUTION

Accepted Solutions

I finally got it working yesterday. Instead of creating a for loop, I make the function run itself again each time it receives a response. Of course, this could go on forever. So I built in a variable called "proceed" that is true or false. Once a limit has been reached (such as 10 photos per step) the loop stops. That's more or less how my code is working. It's a nice trick -- when you want to "pause" a function until something happens, just put the function call inside of the function in order to create a loop:

 

var proceed = true;// change back to false later
var waitUntilFinished = false;

var j = 1;//step
var k = 1;//image
var X = []; // [[chapter1 1,1,1,3,4,1,1,3],[chapter 2, 1,1,1,1,1,2],[chapter 3, 1,1,1]]
var Xm = []; // metadata for X

// Change Image per step
$scope.app.stepImage = function (Achapter=1,Astep=1,Aimg=1){
    $scope.view.wdg['U-20-1']['src'] = 'app/resources/IMAGES/CH-'+Achapter+'_STEP-'+Astep+'_IMG-'+Aimg+'.jpg';
  
    // below is code for finding out if multiple images exist per a step, and if so, showing arrows
    if(Xm[Achapter-1]===undefined){
    waitUntilFinished = true;console.log("**a** X=");console.log(X);
    proceed = true;
    $scope.app.getX(Achapter,Astep,Aimg);
    }
    if(!waitUntilFinished){
     // control visibility of <[]> and image resource
      dispImgArrows(Achapter,Astep,Aimg);console.log("**c**")
    }
}


// Show arrows if multiple images exist per a single step
$scope.app.getX = function(i=1,j=1,k=1){
  var j1=j;var k1=k;//capture original inputs
  if(j>chapters[i-1][4]){console.log("**d**");Xm[i-1]=true;proceed=false;i=1;j=1;k=1;waitUntilFinished=false;$scope.app.stepImage(i,j1,k1)}
  if(X[0]===undefined){
      for(ch=0;ch<chapters.length;ch++){
      X.push([]);Xm.push(undefined);
      for(st=0;st<chapters[ch][4];st++){
      X[ch].push(0);}}}
  if(proceed){
  var name = "CH-"+(i).toString()+"_STEP-"+(j).toString()+"_IMG-"+(k).toString()+".JPG";
          var p = "app/resources/IMAGES/"+name;
              console.log(p);
          $http.get(p).then(successCallback, errorCallback);
          function successCallback(response){
              console.log("i="+i+"\nj="+j+"\nk="+k+"\nX=");
              console.log(X);
              k++;
              X[i-1][j-1]++;
              $scope.app.getX(i,j,k);
          }
          function errorCallback(error){
              k=1;// reset
              j++;// step #
              console.log("chapters =");
              console.log(chapters)
              console.log("i="+i+"\nj="+j+"\nk="+k+"\nX=");
              console.log(X);
              $scope.app.getX(i,j,k);
          }
  }
}

So essentially when you go to a chapter you automatically trigger a function to (1) create an array with sub-arrays for each chapter. (2) populate the sub array for that particular chapter with a list of numbers representing the number of images for each step (3) populate a "meta-data" array Xm that tells you which chapters have been visited and thus the number of images per step has been recorded for them. So for instance, after visiting chapter 2 the variables look something like this X = [[0,0,0,0],[0,0,0,0,0,0,0],[1,1,1,2,1,3,1],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0]] and Xm = [undefined, undefined, true, undefined, undefined]

 

If you want the simplified version of this (the core functionality for a recursive check) then use this code:

var proceed = true;// change back to false later
var j = 1; //step
var k = 1; //image
var X = []; // [[chapter1 1,1,1,3,4,1,1,3],[chapter 2, 1,1,1,1,1,2],[chapter 3, 1,1,1]]
var Xm = [];
// by the way "chapters" is an array with chapter metadata, and chapters[i][4] tells you the number of steps for chapter # i

// Show arrows if multiple images exist per a single step
$scope.app.getX = function(i=1,j=1,k=1){
// this just creates an array X with placeholders [[0,0,0],[0,0],[0,0,0,0]] and Xm
  if(j>chapters[i-1][4]){;Xm[i-1]=true;proceed=false;i=1;j=1;k=1}
  if(X[0]===undefined){
      for(ch=0;ch<chapters.length;ch++){
      X.push([]);Xm.push(undefined);
      for(st=0;st<chapters[ch][4];st++){
      X[ch].push(0);}}}
	  
  if(proceed){
  var name = "CH-"+(i).toString()+"_STEP-"+(j).toString()+"_IMG-"+(k).toString()+".JPG";
          var p = "app/resources/IMAGES/"+name;
          $http.get(p).then(successCallback, errorCallback);
          function successCallback(response){
              k++;
              X[i-1][j-1]++;
              $scope.app.getX(i,j,k); \\ use this instead of a for loop
          }
          function errorCallback(error){
              k=1;// reset
              j++;// step #
              $scope.app.getX(i,j,k);  \\ use this instead of a for loop
          }
   }
}

View solution in original post

7 REPLIES 7

Try this Function;

 

function doesFileExist(urlToFile)
{
var xhr = new XMLHttpRequest();
xhr.open('HEAD', urlToFile, false);
xhr.send();

 

if(xhr.status !="200") {
console.log("File not exist");
}
else {
console.log("File Exist")
}


}

 

doesFileExist('app/resources/Uploaded/FILENAME.ext');

 

 

I hope to be proved helpful

 

 

Giuseppe.

 

additional to suggested option by  @Giuseppe_Fiore

you can use also the $http service e.g. to check if a file (var below jsonFile) is in particular Studio folder:

 

   $http.get('app/resources/Uploaded/' + jsonFile).success(function(data, status, headers, config) {
   console.log("Found :"+jsonFile+" in folder app/resources/Uploaded/");
  })
 .error(function(data, status, headers, config) {
console.log("Could NOT find :"+jsonFile+" in folder app/resources/Uploaded/");                                              
  })

 

OK , I see that here is the key word is in sonorously what I overlooked – so far I think the both suggested methods , which works fine are asynchronous calls

What is exact the problem  so that is necessarily  to use synchronous call ?

Maybe you can use some constucts with the promises as mention in the stack overflow post

Thank you both,

 

@RolandRaytchev , I searched for $http.get(...).sucess and found that it has been replaced in later versions of angular: See StackOverflow:

The .success syntax was correct up to Angular v1.4.3.

For versions up to Angular v.1.6, you have to use then method.

I was able to successfully use 

$scope.app.testA = function(){
var testA = "app/resources/IMAGES/CH-5_STEP-14_IMG-1.jpg";
        $http.get(testA).then(successCallback, errorCallback);
        function successCallback(response){
            console.log(testA+' exists');//success code
        }
        function errorCallback(error){
            console.log(testA+' does not exist');//error code
        }
}

However when I use loops, I run into trouble:

 

This is my code:

// Show arrows if multiple images exist per a single step
var imagesPerStep = []; ///// format: [[chapter1 1,1,1,3,4,1,1,3],[chapter 2, 1,1,1,1,1,2],[chapter 3, 1,1,1]]
$scope.app.multipleImages = function(){
  // When first called, find out which steps have multiple images
  for(i=0;i<chapters.length-1;i++){ // loop through chapters
    imagesPerStep.splice(i,1,[]);// add a sub-array[] for chapter(i)
    for(j=0;j<chapters[i][4];j++){ // loop through steps [4]= #of steps
      imagesPerStep[i].push(0);// create new element (step) within a sub-array (chapter)
      for(k=0;k<10;k++){// loop through images per step
        var name = "CH-"+(i+1).toString()+"_STEP-"+(j+1).toString()+"_IMG-"+(k+1).toString()+".JPG";
        //console.log("name = "+name);
        var p = "app/resources/IMAGES/"+name;
        $http.get(p).then(successCallback, errorCallback);
        function successCallback(response){
            //success code
            imagesPerStep[i][j]++;//if the file exists, add one 
        }
        function errorCallback(error){
            //error code
        }
      }
    }      
  }
}

I think that the problem might be the loop. Before the response ever returns, the loop has already finished and [i] and [j] are no longer the same values. I need to somehow pause the loop until a response is returned.

 

Any ideas on how to pause?

Thanks!

Hi @Wes_Tomer ,

I took a look on your code and I think it could not work.

The problem is when you have the call :

imagesPerStep[i][j]++

 

so, when the call is done you do not know what is the value if i and j... 

I do not think that you need to synchronize it in fact but you need to:

1.) past i an j as arguments to the call of the $http.get() -> example:

 

 

...
  var p = "app/resources/IMAGES/"+name;
  var dataIN=[i,j];
        $http.get(p,dataIN).then(successCallback, errorCallback);
        function successCallback(response){
            //success code
            imagesPerStep[ dataIN[0] ][  dataIN[1] ]++;//if the file exists, add one 
        }
....

 

2.) if there is still problem , you can try  first to initialize  the whole array imagesPerStep[][] over the whole range with 0 and then set to 1 only for the existing objects in the loop .

 

 

I finally got it working yesterday. Instead of creating a for loop, I make the function run itself again each time it receives a response. Of course, this could go on forever. So I built in a variable called "proceed" that is true or false. Once a limit has been reached (such as 10 photos per step) the loop stops. That's more or less how my code is working. It's a nice trick -- when you want to "pause" a function until something happens, just put the function call inside of the function in order to create a loop:

 

var proceed = true;// change back to false later
var waitUntilFinished = false;

var j = 1;//step
var k = 1;//image
var X = []; // [[chapter1 1,1,1,3,4,1,1,3],[chapter 2, 1,1,1,1,1,2],[chapter 3, 1,1,1]]
var Xm = []; // metadata for X

// Change Image per step
$scope.app.stepImage = function (Achapter=1,Astep=1,Aimg=1){
    $scope.view.wdg['U-20-1']['src'] = 'app/resources/IMAGES/CH-'+Achapter+'_STEP-'+Astep+'_IMG-'+Aimg+'.jpg';
  
    // below is code for finding out if multiple images exist per a step, and if so, showing arrows
    if(Xm[Achapter-1]===undefined){
    waitUntilFinished = true;console.log("**a** X=");console.log(X);
    proceed = true;
    $scope.app.getX(Achapter,Astep,Aimg);
    }
    if(!waitUntilFinished){
     // control visibility of <[]> and image resource
      dispImgArrows(Achapter,Astep,Aimg);console.log("**c**")
    }
}


// Show arrows if multiple images exist per a single step
$scope.app.getX = function(i=1,j=1,k=1){
  var j1=j;var k1=k;//capture original inputs
  if(j>chapters[i-1][4]){console.log("**d**");Xm[i-1]=true;proceed=false;i=1;j=1;k=1;waitUntilFinished=false;$scope.app.stepImage(i,j1,k1)}
  if(X[0]===undefined){
      for(ch=0;ch<chapters.length;ch++){
      X.push([]);Xm.push(undefined);
      for(st=0;st<chapters[ch][4];st++){
      X[ch].push(0);}}}
  if(proceed){
  var name = "CH-"+(i).toString()+"_STEP-"+(j).toString()+"_IMG-"+(k).toString()+".JPG";
          var p = "app/resources/IMAGES/"+name;
              console.log(p);
          $http.get(p).then(successCallback, errorCallback);
          function successCallback(response){
              console.log("i="+i+"\nj="+j+"\nk="+k+"\nX=");
              console.log(X);
              k++;
              X[i-1][j-1]++;
              $scope.app.getX(i,j,k);
          }
          function errorCallback(error){
              k=1;// reset
              j++;// step #
              console.log("chapters =");
              console.log(chapters)
              console.log("i="+i+"\nj="+j+"\nk="+k+"\nX=");
              console.log(X);
              $scope.app.getX(i,j,k);
          }
  }
}

So essentially when you go to a chapter you automatically trigger a function to (1) create an array with sub-arrays for each chapter. (2) populate the sub array for that particular chapter with a list of numbers representing the number of images for each step (3) populate a "meta-data" array Xm that tells you which chapters have been visited and thus the number of images per step has been recorded for them. So for instance, after visiting chapter 2 the variables look something like this X = [[0,0,0,0],[0,0,0,0,0,0,0],[1,1,1,2,1,3,1],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0]] and Xm = [undefined, undefined, true, undefined, undefined]

 

If you want the simplified version of this (the core functionality for a recursive check) then use this code:

var proceed = true;// change back to false later
var j = 1; //step
var k = 1; //image
var X = []; // [[chapter1 1,1,1,3,4,1,1,3],[chapter 2, 1,1,1,1,1,2],[chapter 3, 1,1,1]]
var Xm = [];
// by the way "chapters" is an array with chapter metadata, and chapters[i][4] tells you the number of steps for chapter # i

// Show arrows if multiple images exist per a single step
$scope.app.getX = function(i=1,j=1,k=1){
// this just creates an array X with placeholders [[0,0,0],[0,0],[0,0,0,0]] and Xm
  if(j>chapters[i-1][4]){;Xm[i-1]=true;proceed=false;i=1;j=1;k=1}
  if(X[0]===undefined){
      for(ch=0;ch<chapters.length;ch++){
      X.push([]);Xm.push(undefined);
      for(st=0;st<chapters[ch][4];st++){
      X[ch].push(0);}}}
	  
  if(proceed){
  var name = "CH-"+(i).toString()+"_STEP-"+(j).toString()+"_IMG-"+(k).toString()+".JPG";
          var p = "app/resources/IMAGES/"+name;
          $http.get(p).then(successCallback, errorCallback);
          function successCallback(response){
              k++;
              X[i-1][j-1]++;
              $scope.app.getX(i,j,k); \\ use this instead of a for loop
          }
          function errorCallback(error){
              k=1;// reset
              j++;// step #
              $scope.app.getX(i,j,k);  \\ use this instead of a for loop
          }
   }
}
Wes_Tomer
13-Aquamarine
(To:Wes_Tomer)

By the way, if all this code looks confusing, here is the "skeleton" that I built on top of. Hopefully this helps to simplify things a little.

 

$scope.app.getX = function(){
          var myString = "app/resources/IMAGES/filename.jpg";
          $http.get(myString).then(successCallback, errorCallback);
          function successCallback(response){
              // code you want to execute when image IS found
          }
          function errorCallback(error){
              // code you want to execute when image is NOT found
          }
  }
}
Announcements

Top Tags