【发布时间】:2020-07-13 10:21:43
【问题描述】:
我已经设置了一个节点服务器来处理使用 PDFLateX 将乳胶转换为呈现的 pdf 的请求。如果文件需要额外的资产,例如图像我先下载它们,然后开始 pdflatex 进程。如果图像是使用 http.get 客户端下载并使用 fs.createWriteStream 保存的,它们会正确显示在最终文件中。
例如这个 URL 可以正常工作:image over https
现在,如果我通过 http:image over http 提供相同的图像,它会损坏包含在最终 pdf 中的文件。图像会严重失真,但会显示出来。写入文件系统的文件是正确的,但没有损坏。
下载文件的代码如下所示:
const http = require('http');
const https = require('https');
const fs = require('fs-promise');
/**
* Downloads a single Asset
*
* @param url Url to an Image
* @param dest Path where it will be saved
* @returns {Promise}
*/
function download (url, dest) {
console.log('Downloading Asset from: ' + url + ' to ' + dest);
return new Promise((resolve, reject) => {
let file = fs.createWriteStream(dest);
let link = new URL(url);
let client = (link.protocol.includes('https')) ? https : http;
client.get(url, function(response) {
response.pipe(file);
file.on('close', function () {
setTimeout(function () {
resolve();
},10)
});
}).on('error', function(err) {
fs.unlink(dest);
reject();
});
});
}
如您所见,我什至尝试了超时来延迟解析事件,以防“关闭”被提前触发。但这无济于事。 在所有下载过程完成后,我启动 PdfLateX 过程,例如在下面的函数解析之后。
/**
* Downloads all needed Assets to /assets/
*
* @param assetUrls Array of Objects that contain urls and names
* @returns {Promise}
*/
function downloadAssets(assetUrls){
return new Promise((resolve,reject) => {
let requests = [];
if(assetUrls){
assetUrls = JSON.parse(assetUrls);
for(let asset of assetUrls){
requests.push(download(asset.url, './assets/' + asset.name));
}
}
Promise.all(requests)
.catch((err) => {
console.log(err);
reject('Download of one or more assets failed!');
})
.then(() => {
resolve();
});
})
}
这是在 Docker 容器内使用 Node 12.16.2 运行的。
我尝试了几种下载图片的方法,但每次通过 https 提供图片时,最终的 Pdf 中都会损坏,但直接在文件系统中查看 id 时却完好无损。
还有一点需要注意的是,图像总是以同样的方式损坏。没有变化,通过 https 提供的特定图像总是会以相同的方式中断。
任何可能导致此问题的线索将不胜感激,因为我在搜索网络时找不到任何解决方案。
【问题讨论】:
-
对于未来的读者:我发现问题不在于pdf本身的生成,最终文件是正确的。使用最终文件回答初始请求时,图像会损坏。我仍然不知道为什么会发生这种情况和/或为什么只会在图像由 https 提供时才会发生这种情况,但我离解决方案更近了一步。