2016-11-15 7 views
1

Так вот обзор архитектуры моей установки:Узел/Экспресс - запрос POST, чтобы получить почтовый с удаленного сервера, передать обратно клиенту

  • PEBKAC
  • AngularJS Frontend
  • NodeJS/Экспресс Посредник
  • Spring/Hibernate API
  • MySQL Database

Прямо сейчас в Spring API у меня есть вызов API для динамического создания zip-файла. Этот вызов возвращает двоичный поток.

Что мне нужно сделать, это поймать этот поток в узле/экспресс и передать его обратно в интерфейс AngularJS.

Поездка пользователя заключается в том, что пользователь проверяет список экспортируемых товаров, нажимает кнопку для подтверждения экспорта, а HTTP-запрос делается на узел. Затем узел отправляет запрос Spring, который возвращает поток, и отправляет результат обратно в AngularJs.

Не нужно никаких лекций о том, как мы не должны иметь Node/Express или Spring - архитектура изменится, и сейчас это много устаревшего кода.

Текущий Экспресс запрос на Spring:

exports.zipRequest = function(path, postBody, onResult) { 

    var options = { 
     host: host, 
     port: port, 
     path: springContext + path, 
     method: 'POST', 
     encoding: 'binary', 
     headers: { 
      'Content-Type': 'application/json', 
      'Accept': 'application/zip' 
     } 
    }; 

    var req = http.request(options, function (res){ 

     var output = ''; 
     res.setEncoding('binary'); 

     res.on('data', function (chunk) { 
      output += chunk; 
     }); 

     res.on('end', function() { 
      onResult(res.statusCode, output); 
     }); 


    }).on('error', function(e) { 
     console.log("Got error: " + e.message); 
     req.end(); 
    }); 

    req.write(postBody.toString()); 
    req.end(); 
}; 

Текущий узел API:

exports.exportSessions = function(req, res) { 

    var dataset = req.user.dataset; 
    var id = req.params.id; 

    var arr = JSON.stringify(req.body); 

    var today = new Date(); 
    var filename = today.toISOString(); 
    filename = filename.replaceAll("-","_"); 
    filename = filename.replaceAll(":","_"); 
    filename = filename.replace(".","_"); 

    var path = '/Export/dataset/'+dataset+'/exportZip/'; 

    api.zipRequest(path, arr, function(statusCode, result) { 

     if(statusCode != 200) { 

      console.log(statusCode); 
      console.log(result); 
      res.send(statusCode, "Problem from backend API"); 

     } else { 

      if (result != null || typeof result != 'undefined') { 

       res.type('application/zip') 
       res.attachment(filename+'.zip'); 
       res.send(result, 'binary'); 

      } else { 

       res.send(statusCode, "Undefined Result" + result); 

      } 
     } 
    }); 

}; 

Глядя, чтобы выяснить, как получить браузер клиента, чтобы сохранить возвращаемый файл - как я могу видеть двоичный string fine, и я устанавливаю все необходимые заголовки. Я пробовал все от создания буфера в выражении и возвращаю его в res.write() в ответе API узла и ничего не работает.

EDIT:

Так что мне удалось получить Экспресс Pipe почтовый обратно клиенту в полном объеме, используя следующие:

var req = http.request(options, function (res){ 

     var today = new Date(); 
     var filename = today.toISOString(); 
     filename = filename.replaceAll("-","_"); 
     filename = filename.replaceAll(":","_"); 
     filename = filename.replace(".","_"); 

     res.setEncoding('binary'); 

     res.pipe(onResult); 
}; 

и в узле:

exports.exportSessions = function(req, res) { 

    var dataset = req.user.dataset; 
    var id = req.params.id; 

    var arr = JSON.stringify(req.body); 

    var today = new Date(); 
    var filename = today.toISOString(); 
    filename = filename.replaceAll("-","_"); 
    filename = filename.replaceAll(":","_"); 
    filename = filename.replace(".","_"); 

    var path = '/Export/dataset/'+dataset+'/exportZip/'; 
    res.type('application/zip') 
    res.attachment(filename+'.zip'); 
    return api.zipRequest(path, arr, res); 
} 

Я вижу в консоли разработчика, что все потоки файлов для клиента (браузера) и заголовки ответов следующие:

access-control-allow-headers:Origin, Content-Type, X-Auth-Token 
access-control-allow-methods:POST, GET 
access-control-allow-origin:* 
cache-control:private, no-cache, must-revalidate 
Connection:keep-alive 
content-disposition:attachment; filename="2016_11_16T09_34_50_976Z.zip" 
content-type:application/zip 
Date:Wed, 16 Nov 2016 09:34:51 GMT 
expires:-1 
Transfer-Encoding:chunked 
X-Powered-By:Express 

По-прежнему нет кубиков при получении приглашения на сохранение.

ответ

1

Итак, я, наконец, понял это. Надеюсь, это даст довольно подробный ответ любому, кто хочет провести первоначальный запрос и передать ответ от вторичного.

Я решил эту проблему с помощью модуля NPM request, и изменения моего узла API вызова от POST на GET:

var request = require('request'); 

exports.exportSessions = function(req, res, next) { 

    var dataset = req.user.dataset; 
    var arr = decodeURIComponent(req.query.ids); 

    var path = '/Export/dataset/'+dataset+'/exportZip/'; 
    console.log('Exporting Data '+arr); 

    var options = { 
     method: 'POST', 
     uri: 'http://' + api.host + ':' + api.port + api.springContext + path, 
     headers: { 
      'Content-Type': 'application/json', 
      'Accept': 'application/zip' 
     }, 
     json: true, 
     body: JSON.parse(arr) 
    }; 

    request.post(options).pipe(res) 
} 

и меняет Угловой запрос просто открыть новое окно с ГЕТ URL:

$scope.exportData = function() { 
    var ids = $scope.sessions.selected.map(function(ses){ 
     return ses.id; 
    }); 
    var pars = encodeURIComponent(JSON.stringify(ids)); 
    window.open('/api/sessions/export/sessions?ids='+pars+'&access_token='+Auth.getToken(), '_blank'); 
} 

Это открывает новое окно на короткое время с путем API NodeJS, который затем называет Spring/Hibernate API и трубу ответа обратно в ответ на первоначальный запрос.

В последней строке API-интерфейса Node используется request, чтобы сделать запрос POST на сервер Spring/Hibernate и передать ответ обратно через начальный объект res. Надеюсь, это поможет любому, кто хочет передать удаленные двоичные файлы обратно клиенту.