2016-06-27 2 views
1

Wir entwickeln eine App mit Recurly-Integration und versuchen, es PDF-Rechnungsfunktion zu verwenden.Recurly pdf Rechnungsabruf mit JavaScript und Node.js (Meteor)

Die App basiert auf Node.js (Meteor-Plattform).

Er empfängt richtige Antwort aus Recurly mit Binärdatei:

Recurly

Aber ich kann es nicht richtig speichern. Ich habe zwei Möglichkeiten versucht: es auf der Client-Seite in Browser drucken:

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

Und es direkt auf dem Server (nur Test) speichern:

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

Aber in beiden Fällen habe ich beendet up mit nicht funktionierenden pdf-Datei. Acrobat, Foxit Reader und Chrome können diese Datei nicht öffnen - sie ist beschädigt.

Haben Sie Vorschläge, wo ich falsch liege? Vielleicht brauche ich eine Inhaltskonvertierung, bevor ich sie oder etwas anderes speichere?

Added

Das Ergebnis dieser Anfrage Ich habe (Bild oben) in Konsole-Client und gedruckt gesendet.

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

Wie haben Sie die Daten erhalten? Haben Sie den 'blob' responseType gesetzt? – MasterAM

+0

@MasterAM Ich habe immer wieder Dokumente verwendet, um die Daten zu erhalten. https://dev.recurly.com/docs/lookup-invoice-details –

+0

Dies beinhaltet keine JS-API. Kannst du etwas Code posten? – MasterAM

Antwort

2

Das Problem besteht darin, dass Sie versuchen, eine Binärdatei mit einer Anfrage zu erhalten, die eine codierte Zeichenfolge als Antwort erwartet.

Die beste Option besteht darin, der Anforderungsbibliothek mitzuteilen, was sie erwarten sollte. Andernfalls müssen Sie die Binärdaten manuell aus der UTF-16 - oder UTF-8 -codierten Zeichenfolge entfernen.

Es gibt einen Unterschied zwischen den Client- und Serverimplementierungen.


Server

Der Server Implementierung verwendet request Modul des Knotens. Sie können supply options for it mit npmRequestOptions verwenden.

Wie in der Dokumentation angegeben:

Codierung - Encoding bis auf setEncoding der Antwortdaten verwendet werden. Wenn null, wird der Körper als Puffer zurückgegeben. Alles andere (einschließlich des Standardwerts von undefined) wird als Codierungsparameter an toString() übergeben (was bedeutet, dass dies standardmäßig utf8 ist). () Hinweis: Wenn Sie Binärdaten erwarten, sollten Sie Codierung: null festlegen.)

also auf dem Server können Sie so etwas wie:

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

Client

Die Client-Implementierung verwendet XHR.

Um die binäre Antwort zu verarbeiten, müssen Sie die XHR responseType in (vorzugsweise) 'blob' ändern.

Leider sehe ich keine Möglichkeit, einen binären Blob in Meteor aktuelle Implementierung des HTTP-Pakets zu erhalten, wie es die Antwort erwartet, um eine responseText zu haben.

Sie können direkt ein XMLHttpRequest Objekt verwenden, aber Sie müssen möglicherweise einige Wrapper-Code, um sterbenden Browsern zu unterstützen (IE6, ich sehe dich an! - die üblichen new ActiveXObject('Microsoft.XMLHttp'); Tanz).

dies erreicht werden könnte so etwas wie den folgenden Code:

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

, die eine XHR sendet, die die Antwort in ein binäres Blob kodiert und eine ObjectURL mit den richtigen Daten erzeugt.

+0

vielen Dank! 'encoding: null' - war der Schlüssel, jetzt erhalte ich eine PDF korrekt von einem Server. Denn jetzt verwende ich Base64-Codierung für das Anfrageergebnis 'return new Buffer (result.content) .ToString ('base64');' Und es dann auf dem Client 'window.open mit JavaScript öffnen (“ Daten: application/pdf; base64, "+ r);' Aber wie ich weiß, ist es nicht die beste Option? Ich habe einige Möglichkeiten zum Übergeben von Binärdateien von Node.js an Client untersucht, aber die Lösung noch nicht gefunden. Haben Sie Ideen, wie Sie pdf vom Client zum Server auf die beste Weise übertragen können? Wie auch immer, vielen Dank noch einmal für Ihre Hilfe! –