Попытка извлечь все изображения из папки вне server.js область видимости

#node.js #angularjs

#node.js #angularjs

Вопрос:

Я работаю над тем, что будет встроенным веб-сайтом для аппаратного обеспечения с файловой структурой, если только определенные папки будут иметь доступ для чтения / записи. Мой server.js вместе с реализацией angularjs они будут находиться в каталоге, доступном только для чтения, однако мне нужно отобразить изображения, которые будут храниться в отдельном каталоге, который будет иметь права на чтение / запись, поскольку конечный пользователь может добавлять изображения в папку.

Я знаю, что могу прочитать и отправить все файлы из NodeJS в AngularJS с помощью этого кода:

 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);
    })
  })
})
  

Проблема, с которой я сталкиваюсь, заключается в том, что я не знаю, как заставить мой интерфейс ждать всех ответов, поскольку вышеуказанное отправит по одному res на файл, но AngularJS перестает прослушивать res после поступления первого once.

Вот моя функция контроллера AngularJS:

   $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);
  });
  

и моя фабрика, которая является всего лишь базовым запросом

   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);
    })
  }
  

Моими ожидаемыми результатами был бы массив, полный URL-адресов файлов, чтобы я мог выполнить ng-repeat в массиве servericon и отобразить изображения с тегом img

Ответ №1:

Как только вы звоните res.end() , ответ считается завершенным, и вы больше ничего не можете отправить. Вместо этого вы должны получать все данные изображения, объединяя их в один буфер. Это выглядело бы примерно так:

 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())
  

Это приведет к перебору каждого файла в каталоге и отправке результата в массив обещаний, каждое из которых будет разрешено в буфер, содержащий изображение.

Теперь на стороне клиента вам нужно будет захватить общий буфер, а затем разделить его с помощью разделителя. Что-то вроде этого будет работать:

 $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);
  })
});