2016-06-27 5 views
1

私たちはRecurlyインテグレーションを使用してアプリを開発しており、PDFインボイス機能を使用しようとしています。JavaScriptとNode.js(Meteor)を使用して定期的にPDFインボイスを取得します

このアプリはNode.js(Meteorプラットフォーム)に基づいています。

それはバイナリファイルでRecurlyから正しい答えを受け取る:

Recurly

しかし、私はそれを正しく保存することはできません。私は、次の2つの方法を試してみた:

var file = window.URL.createObjectURL(new Blob([r.content], {type: "application/pdf"})); 
    var a = document.createElement("a"); 
    a.href = file; 
    a.download = "invoicePDF"; 
    document.body.appendChild(a); 
    a.click(); 

    window.onfocus = function() { 
    document.body.removeChild(a) 
    } 

をと(単なるテストのために)サーバー上で直接それを保存します:ブラウザでクライアント側でそれを印刷

var fs = require('fs'); 
var wstream = fs.createWriteStream('C:/recurly.pdf'); 
wstream.write(result.content); 
wstream.end(); 

しかし、私は終了しました両方のケースで非稼動のpdfファイルでアップ。 Acrobat、Foxitリーダー、Chromeでこのファイルを開くことはできません。破損しています。

私が間違っているところはありますか?たぶん私はそれを保存する前にいくつかのコンテンツの変換が必要ですか?

を追加しました

私はクライアントに送信され、コンソール(上の画像)で印刷しました。この要求の結果。

try { 
     result = HTTP.call(
     'GET', 
     'https://' + Meteor.settings.recurly.SUBDOMAIN + '.recurly.com/v2/invoices/' + invoiceId, 
     { 
      headers: { 
      Authorization: "Basic " + (new Buffer(Meteor.settings.recurly.API_KEY)).toString('base64'), 
      Accept: 'application/pdf' 
      } 
     } 
    ); 
    } catch (err) { 
     result = e; 
    } 
+0

データをどのように入手しましたか? 'blob'レスポンスタイプを設定しましたか? – MasterAM

+0

@MasterAMデータを取得するために定期的にドキュメントを使用しました。 https://dev.recurly.com/docs/lookup-invoice-details –

+0

これにはJS APIは含まれていません。いくつかのコードを投稿できますか? – MasterAM

答えて

2

問題は、エンコードされた文字列を応答として要求する要求を含むバイナリファイルを取得しようとしていることです。

リクエストライブラリに期待する内容を伝えることをお勧めします。それ以外の場合は、UTF-16 - またはUTF-8エンコード文字列から手動でバイナリデータを読み込まなければなりません。

クライアントとサーバーの実装には違いがあります。


サーバー

サーバの実装は、ノードのrequestモジュールを使用しています。 npmRequestOptionsを使用してsupply options for itを入力することができます。その文書に記載されているとおり

エンコーディング - 応答データのsetEncodingで使用するエンコード。 nullの場合、本文はBufferとして返されます。それ以外のもの(未定義のデフォルト値を含む)は、エンコードパラメータとしてtoString()に渡されます(これはデフォルトで有効にutf8になります)。 (注:バイナリデータが必要な場合は、encoding:nullを設定する必要があります。

try { 
    result = HTTP.call(
    'GET', 
    'https://' + Meteor.settings.recurly.SUBDOMAIN + '.recurly.com/v2/invoices/' + invoiceId, 
    { 
     headers: { 
     Authorization: "Basic " + (new Buffer(Meteor.settings.recurly.API_KEY)).toString('base64'), 
     Accept: 'application/pdf' 
     }, 
     npmRequestOptions: { 
     encoding: null // will cause the result to be stored in a binary Buffer 
     } 
    } 
); 

    // will write the file in binary mode 
    fs.writeFile(outFileName, res.content, 'binary'); 
} catch (err) { 
    result = e; 
} 

クライアント

クライアントの実装では、XHRを使用しています:

ので、サーバー上で次のような何かを行うことができます。

バイナリ応答を処理するには、XHRのresponseTypeを(好ましくは)'blob'に変更する必要があります。

残念ながら、応答がresponseTextであると予想されるため、MeteorのHTTPパッケージの現在の実装では、バイナリBLOBを取得する方法はありません。

XMLHttpRequestオブジェクトを直接使用できますが、死にかけているブラウザ(IE6、私はあなたを見ています - 通常のnew ActiveXObject('Microsoft.XMLHttp');のダンス)をサポートするためにラッパーコードを追加する必要があります。

これは、次のコードのような使用して達成することができる:

var xhr = new XMLHttpRequest(); 
xhr.open('GET', url, true); 
xhr.setRequestHeader('Authorization', ...); 
xhr.responseType = 'blob'; // this is key 

xhr.onload = function(e) { 
    if (this.status == 200) { 
    // this.response is a Blob. If you are sure that it is of the 
    // correct content-type, you can use it to construct the URL directly 
    let blob = new Blob([this.response], {type: 'application/pdf'}); 
    let url = URL.createObjectURL(blob); 
    let a = document.createElement("a"); 
    a.href = url; 
    a.download = "invoice.pdf"; 
    document.body.appendChild(a); 
    ... 
    } 
}; 

xhr.send(); 

バイナリBLOBに応答を符号化し、正しいデータを用いているObjectURLを生成XHRを送信します。

+0

ありがとうございました! 'encoding:null'がキーになったので、今度はサーバによってpdfが正しく受信されます。今の 私は要求結果のために '新しいバッファ(result.content).toString(「base64で」)を返すBase64エンコードを使用します。「(' そしてクライアント 'のwindow.openのJavaScriptでそれを開くとデータ:application/pdf; base64、 "+ r);' しかし私はそれが最良の選択肢ではないと知っていますか? BinaryファイルをNode.jsからClientに渡すためのいくつかの方法を調査しましたが、解決策はまだ見つかりませんでした。 最良の方法でクライアントからサーバーにpdfを転送する方法はありますか? とにかく、もう一度ご協力いただきありがとうございます。 –

関連する問題