2016-11-15 3 views
1

に渡す:ノード/エクスプレス - リモートサーバからzipファイルを受信するためのPOSTリクエスト、だからここに私のセットアップのアーキテクチャの概要だバッククライアント

  • PEBKAC
  • AngularJSフロントエンド
  • NodeJS/Expressの仲介
  • 春/ HibernateのAPI
  • MySQLデータベース

現在、Spring APIには、zipファイルを動的に生成するためのAPI呼び出しがあります。この呼び出しは、チャンクされたバイナリストリームを返します。

ノード/エクスプレスでこのストリームを捕捉し、AngularJSフロントエンドに戻す必要があります。

ユーザは、エクスポートするアイテムのリストをチェックアウトし、ボタンをクリックしてエクスポートを確認し、ノードに対してhttpリクエストが行われるということです。次に、ノードは、ストリームを返す要求をSpringに送信し、その結果をAngularJsに返します。

Node/Expressや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); 

      } 
     } 
    }); 

}; 

- 私はバイナリを見ることができるように文字列の罰金、私は必要なすべてのヘッダーを設定しています。私はエクスプレスでバッファを作成し、それをノードAPIレスポンスのres.write()に戻してみましたが、何も動作していないようです。

EDIT:

だから私は、次を使用して郵便番号、クライアントにその全体がパイプにExpressを得ることができました:

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

だから私はそれを最後に理解しました。うまくいけば、これは最初のリクエストを保持し、セカンダリからの応答を返すことを望んでいる誰かにかなり深い答えを与えるでしょう。単にGETのURLで新しいウィンドウを開くために、私の角度の要求を

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

と変更:

は私がNPM requestモジュールを使用して、GETへのPOSTからの私のノードのAPI呼び出しを変更することで、これを解決します:

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

これは、その後、元の要求に対する応答として応答春/ HibernateのAPIとのパイプを呼び出すNodeJS APIパスで簡単に新しいウィンドウを開きます。

ノードAPIの最後の行は、requestを使用して、Spring/HibernateサーバーにPOST要求を行い、応答を最初のresオブジェクト経由でパイプします。うまくいけば、これは他の人がクライアントにリモートバイナリファイルを返すのを助けるのに役立ちます。

関連する問題