简体   繁体   中英

Attempting to retrieve all images from a folder outside server.js scope

I am working on what will be an embedded website for a piece of hardware with a file structure were only certain folders have read/write access. My server.js along with the angularjs implementation will be in a read only directory, however I need to display images that are going to be stored in a separate directory that will have read/write privileges as the end user can add images to the folder.

I know I can read and send all the files from NodeJS to AngularJS with this code:

fs.readdir(fileDirectory, function(err,files){
  files.forEach(function(file){
    console.log('got file', file)
    fs.readFile(fileDirectory + file, function(err, buffer){
      var base64Image = new Buffer(buffer, 'binary').toString('base64');
      // res.send(base64Image);
      res.end(base64Image);
    })
  })
})

The problem I'm facing is I don't know how to have my frontend wait for all of the responses as the above will send one res per file, but angularJS stops listening for a res after the first once comes.

Here is my AngularJS controller function:

  $scope.servericon = [];
  var iconarray = fmsFactory.getAllIcons().then(function(res){
    console.log('controller got', res);
    blob = b64toBlob(res.data, 'image/png')
    blobUrl = URL.createObjectURL(blob);
    img = document.createElement('img');
    img.src = blobUrl.slice(5, blobUrl.length)  //remove blob: from url
    $scope.servericon.push(img.src)
    // document.getElementByID('library').appendChild(img);
  });

and my factory which is just a basic request

  factory.getAllIcons = function(callback){
    return $http({
      url: '/allIcons',
      method: 'GET'
    }).then(function(res){
      console.log('success', res);
      return res
    }, function(res){
      console.log('something went wrong', res);
    })
  }

My expected results would be an array full of URL's to the files so that I can perform an ng-repeat on the servericon array and render the images with an img tag

Once you call res.end() , the response is considered complete and you can't send anything else. Instead, you should be getting all the image data, combining it to a single buffer. It would look something like this:

let promises = [];
fs.readdir(fileDirectory, function(err,files){
  promises.push(new Promise((resolve, reject) => {
    files.forEach(function(file){
      console.log('got file', file)
      fs.readFile(fileDirectory + file, function(err, buffer){
        var base64Image = new Buffer(buffer, 'binary').toString('base64');
        resolve(base64Image);
      })
    })
  }))
})

Promise.all(promises).resolve(base64Image => {
  res.send(base64Image)
  res.send('\n::\n')  // choose any delimiter that you can split on
}).then(() => res.end())

This will iterate through each file in the directory and push the result to an array of promises that will each resolve to the Buffer containing the image.

Now, on the client side, you will need to grab the overall buffer and then split it up using the delimiter. Something like this will work:

$scope.servericon = [];
var iconarray = fmsFactory.getAllIcons().then(function(res){
  console.log('controller got', res);
  res.data.split('\n::\n').forEach(blob => {
    blob = b64toBlob(res.data, 'image/png')
    blobUrl = URL.createObjectURL(blob);
    img = document.createElement('img');
    img.src = blobUrl.slice(5, blobUrl.length)  //remove blob: from url
    $scope.servericon.push(img.src)
    // document.getElementByID('library').appendChild(img);
  })
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM