Получить ответ в функции AngularJS из файла res.send csv - PullRequest
0 голосов
/ 28 октября 2019

Мне нужно перехватить ответ (я имею в виду проверку, когда ответ от функции NodeJS возвращается клиенту, а не ошибка) из функции NodeJS.
Когда кнопка нажата, запускается функция с формойи NodeJS после запроса возвращает CSV-файл. Проблема в том, что запрос сложный и для его выполнения требуется более 1 минуты.

Мне нужно запустить загрузочный спиннер при нажатии кнопки, и он должен остановиться, когда CSV возвращается из функции. Любая подсказка о том, как я могу это сделать? Заранее спасибо.

HTML-форма

<form name="csvForm" ng-submit="download(csvForm.$valid)">
  <div class="panel-body">
    <div class="row">
      <div class="form-group col-sm-4">
        <label class="control-label">Concessionaria<span ng-if="userProfileID != 1">*</span></label>
        <select class="form-control" ng-model="Dealer"
                ng-options="dealer.ID as dealer.Name for dealer in dealers " 
                ng-required="userProfileID != 1">
          <option value=""></option>
        </select>
      </div>

      <div class="form-group col-sm-4">
        <label class="control-label">Anno*</label>
        <select class="form-control" ng-model="Year"
                ng-options="y as y for y in syears" required>
          <option value=""></option>
        </select>
      </div>
    </div>


  </div>
  <div class="form-group col-sm-4 col-sm-offset-4" style="margin-top:20px">
    <button name="submitBtn" class="btn btn-lg btn-primary btn-block" type="submit" >Scarica CSV</button>
  </div>
</form>

Угловой

$scope.download = function () {

   var form = document.createElement('form');
   form.action = apihost + "/queryReport/avanzEvaluation"; 
   form.method = 'POST';
   form.target = '_blank';
   form.style.display = 'none';

   var jsonData = {
      dealer: $scope.Dealer,
      year: $scope.Year
   };

   var inputJson = document.createElement('input');
   inputJson.type = 'text';
   inputJson.name = 'data';
   inputJson.value = JSON.stringify(jsonData);

   var submit = document.createElement('input');
   submit.type = 'submit';
   submit.id = 'submitProject';
   form.appendChild(inputJson);
   form.appendChild(submit);
   document.body.appendChild(form);

   //Send form.
   form.submit();
   document.body.removeChild(form);
};

NodeJS

router.post('/avanzEvaluation', function (req, res) {
    return new Promise(function(resolve,reject) {

        //Not the real query, just an example
        var sql = "SELECT * FROM Table ";

        return models.sequelize.query(sql, {replacements: replacements, type: models.sequelize.QueryTypes.SELECT })
        .then(function (results) {

            const Json2csvParser = require('json2csv').Parser;

            //Not real fields, just examples
            const fields = ["Field1", "Field2", "Field3", "Field4",];

            const opts = { fields };

            try {
                const parser = new Json2csvParser(opts);
                const csv = parser.parse(results);
                var filename = ("avanzValutazioni.csv");

                res.header("Content-Disposition","attachment;filename=" + filename); 
                res.setHeader('content-type', 'text/csv');
                res.send(iconv.encode(csv, 'iso-8859-1'));
            }
            catch (err) {
                console.error(err);
            }
        })
        .catch(function (err) {
            console.log(err);
        }); 
    })
});

Ответы [ 2 ]

0 голосов
/ 30 октября 2019

Я понял, как это сделать, благодаря @georgeawg тоже!
Я решил, вернув json с именем файла и завершив csv (формат csv), не загружая его из функции NodeJS в интерфейс. Затем я манипулирую результатом в переднем конце, чтобы запустить загрузку CSV с результатом.

AngularJS

$scope.download = function () {
   //Spinner
   usSpinnerService.spin('spinner-1');

   //Custom data from the Form, sent as a JSON
   var jsonData = {
      year: $scope.Year
   };
   if($scope.Dealer) {
      jsonData.dealer = $scope.Dealer;
   }

   //I've could have done this with a options variable, but i prefer it inline
   $http.post(apihost + "/queryReport/avanzEvaluation_TEST", {data: jsonData}, {headers: {'Content-Type': 'application/json'}})
   .success(function (result) {

      //If the query returns a non-empty csv
      if(result.csv.length > 0) {
         usSpinnerService.stop('spinner-1');

         //This if-else is used to make it work on Edge too
         if (window.navigator.msSaveOrOpenBlob) {
            var blob = new Blob([result.csv]);
            window.navigator.msSaveOrOpenBlob(blob, result.filename);
         } 
         else {
            var a = document.createElement("a");
            a.href = "data:attachment/csv," +  encodeURIComponent(result.csv);
            a.target = "_blank";
            a.download = result.filename;
            document.body.appendChild(a);
            a.click();
         }
      }
      //Otherwise I show an error with the module Notification
      else {
         Notification.error("Non è stato possibile eseguire il download del file CSV.");
      }       
   });
}

УзелJS

router.post('/avanzEvaluation_TEST', function (req, res) {
    return new Promise(function(resolve,reject) {

        //Not the real query, just an example
        var sql = "SELECT * FROM Table ";

        return models.sequelize.query(sql, {replacements: replacements, type: models.sequelize.QueryTypes.SELECT })
        .then(function (results) {

            const Json2csvParser = require('json2csv').Parser;

            //Not real fields, just examples
            const fields = ["Field1", "Field2", "Field3", "Field4",];

            const opts = { fields };

            try {
                const parser = new Json2csvParser(opts);
                const csv = parser.parse(results);
                var filename = ("avanzValutazioni.csv");

                res.json({filename: filename, csv: csv});
            }
            catch (err) {
                console.error(err);
            }
        })
        .catch(function (err) {
            console.log(err);
        }); 
    })
});
0 голосов
/ 28 октября 2019

Чтобы запустить и остановить спиннер с помощью службы http, используйте метод .finally обещания $http:

 $scope.spinner = true;
 var promise = $http.post(url, data);
 promise.finally(function() {
     $scope.spinner = false;
 });
 <div ng-if="spinner">
    <!-- Put spinner here -->
 </div>

Для получения дополнительной информации см.

...