用JavaScript和Node.js(meteor)检索返回的pdf发票

我们正在开发一个与Recurly集成的应用程序,并试图使用它的PDF发票function。

该应用程序基于Node.js(meteor平台)。

它从二进制文件接收Recurly的正确答案:

Recurly

但是我不能正确保存它。 我已经尝试了两种方法:在浏览器的客户端打印:

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

并将其直接保存在服务器上(仅供testing):

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

但在这两种情况下,我已经结束了非工作的PDF文件。 Acrobat,Foxit阅读器和Chrome不能打开这个文件 – 已经损坏了。

你有什么build议,我错了吗? 也许我需要一些内容转换之前保存或其他任何东西?

添加

这个请求的结果我已经发送到客户端,并在控制台中打印(上图)。

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

问题是你正在试图获得一个二进制文件的请求,预计编码string作为响应。

你最好的select是告诉请求库它应该期望什么,否则你将不得不手工从UTF-16UTF-8编码string中撬出二进制数据。

客户端和服务器实现是有区别的。


服务器

服务器实现使用节点的request模块。 您可以使用npmRequestOptions 提供选项 。

正如其文件所述:

编码 – 编码用于setEncoding响应数据。 如果为null,则正文返回为Buffer。 其他任何东西(包括未定义的默认值)都将作为编码parameter passing给toString()(这意味着默认情况下是有效的)。 ( 注意:如果你期望二进制数据,你应该设置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'

不幸的是,我没有办法在Meteor当前实现的HTTP包中获取二进制blob,因为它预期响应具有responseText

您可以直接使用XMLHttpRequest对象,但是您可能需要添加一些包装代码来支持垂死的浏览器(IE6,我正在看你!) – 通常new ActiveXObject('Microsoft.XMLHttp'); dance)。

这可以通过使用类似下面的代码来实现:

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

它发送一个XHR,将响应编码成一个二进制Blob,并用正确的数据生成一个ObjectURL。

Interesting Posts