长时间读者,第一次海报。
我正在尝试使用nodejs Server(Express)作为中间的服务层生成一个从SSRS生成PDF文件,并将其提供给最终用户。我们不想将任何与SSR有关的内容揭露给用户,因此我将节点服务器放在一起并使Get request of to Server。
问题是,我可以通过SSR的响应主体获取PDF并将其传递到HTML页面,但是尽管页面计数和文件大小是正确的,但文件完全空白。即使我将数据写入文件作为测试,也会发生这种情况。
在Web浏览器中使用Postman或curl或从Chrome进行直接获取请求时,它将文件成功加载为附件,而没有正体。但是,当我通过节点进行相同的获取请求时,我会得到一个标题,声称有一个附件以及一个包含PDF代码的正文,我只能想象它在击中我的节点服务器时已转换为UTF-8编码。因为该报告是通过SSR生成的,所以我无法使用Express的响应。Download()或类似的功能主义者,因为我在生成PDF之前没有确切的路径。
使事情变得更加复杂,我必须依靠限于HTTP-NTLM库中的请求来从我们的SSRS服务器中获取响应,因此,我无法获得最大的知识,因此,管道和类似的方法是我无法获得的。。我之所以选择这主要是因为它允许我通过HTTP而不是https访问SSR(我们的SSR配置对HTTPS没有响应)。
节点服务器函数:
exports.getReportPDF = function (req, resp)
{
//-Gets the link info from the client side
var myLink = req.body;
var fileLink = myLink.Data;
httpntlm.post({
url: fileLink,
username: 'username',
password: 'password',
workstation: 'workstation',
domain: 'domain'
}, function (err, res){ //-Returns once the stream is complete
if(err) return err;
var resBase64 = new Buffer(res.body).toString('base64');
resp.setHeader('Content-Type', 'application/octet-stream');
resp.setHeader('Content-Transfer-Encoding', 'base64');
fs.writeFile("somethingToCheckAgainst.pdf", resBase64, function(writeErr) {
if(writeErr) {
console.log(writeErr);
} else {
console.log("The file was saved!");
}
});
console.log(resp.get('Content-Disposition'));
resp.send(resBase64);
});
}
客户端功能部分:
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
var results = xmlhttp.responseText;
window.open("data:application/pdf;base64, " + results);
}
}
这是一个快速而肮脏的原型,因此我不关心速度和凌乱的代码,但首选干净而简单。如何获得在新窗口中打开的PDF,或在服务器上创建的窗口打开的PDF以正确显示(不是完全空白)?这是节点与SSR的数据相互作用的问题,还是由我处理数据的方式引起的?
我在相当长的一段时间内遇到了同样的问题。试图成为一个好公民,并在经过几天的故障排除后发布了什么为我解决的问题,因为答案似乎没有出现在互联网上的其他任何地方。
在httpntlm.post中,添加另一个选项 - "二进制:true"。如果您不这样做,则发现响应。Body会自动转换为UTF-8字符串,该字符串损坏PDF并导致其显示为空白。
即使http-ntlm
没有为您提供流式传输的选项,也不需要将数据写入磁盘,也不需要将其编码为base64。您可以简单地创建自己的可读流。替换的resumer
NPM模块使其变得既干净又干净。将其工作到您的NTLM回调中,看起来像这样:
var resumer = require('resumer');
function (err, res){ //-Returns once the stream is complete
if(err) return next(err);
var buffer = new Buffer(res.body);
var stream = resumer().queue(buffer).end();
resp.setHeader('Content-disposition', 'attachment; filename=out.pdf');
resp.setHeader('Content-type', 'application/pdf');
stream
.pipe(resp)
.on('error', next);
};
还请注意,我正在使用第三个中间件参数next
来处理任何错误。只需像您那样做if(err) return err;
,这无济于事。