我正在创建一个需要显示大量PDF的nw.js应用程序。首次启动应用程序时,最初会下载PDF。在初始化阶段,我还需要为列表中显示的每个PDF创建一个缩略图。
当我们有一些PDF时,缩略图生成本身似乎不是问题。它的工作原理是创建一个canvas元素,让PDF.js绘制第一页,然后将画布保存为PNG。
问题是PDF.js似乎无法在运行之间卸载PDF。加载20个1MB的PDF文件通常会导致使用大约500MB RAM的nw.js。现在我们将有100多个,甚至数千个PDF,所以我们需要弄清楚如何释放每个缩略图之间的RAM,因为大约80左右的PDF,nw.js已经使用2GB的RAM并冻结我的笔记本电脑,因为它内存耗尽。
我做了一个简单的测试,显示了这个问题:
var fs = require("fs");
var Q = require("q");
var glob = require("glob");
var canvas = document.createElement("canvas");
var ctx = canvas.getContext('2d');
PDFJS.workerSrc = "pdf.worker.js";
function pdf(pdfFile) {
return new Q.Promise(function (fulfill, reject) {
PDFJS.getDocument(pdfFile).then(function (pdf) {
pdf.getPage(1).then(function (page) {
var viewport = page.getViewport(0.5);
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
page.render(renderContext).then(function () {
//set to draw behind current content
ctx.globalCompositeOperation = "destination-over";
//set background color
ctx.fillStyle = "#ffffff";
//draw background / rect on entire canvas
ctx.fillRect(0, 0, canvas.width, canvas.height);
var img = canvas.toDataURL("image/png");
img = img.replace(/^data:image\/png;base64,/, "");
fs.writeFile(pdfFile + ".png", img, 'base64', function (err) {
console.log("Done thumbnail for: " + pdfFile);
fulfill();
});
});
});
});
});
}
glob("pdf/*.pdf", function (err, files) {
if (err) {
console.log(err);
} else {
function generate(file) {
console.log("Generating thumb for: " + file);
pdf(file).then(function() {
if(files.length > 0) next();
});
}
function next() {
var file = files.pop();
generate(file);
}
next();
}
});
我之前从未做过这样的事情。我试图为所有拇指重复使用相同的画布,但这似乎并没有改变一件事。
我曾尝试在开发人员工具中执行堆快照,以查看占用所有内存的内容,但猜猜是什么?它似乎在执行快照之前触发垃圾收集,因此在执行快照之前nw.js从500MB变为大约100MB。这让我相信对象实际上被标记为删除,但GC在计算机耗尽RAM之前从未有机会运行。加载20个文件,然后等待,但不会触发GC,也不会耗尽RAM。
我已经尝试检查PDF.js的API和文档,但在下载之前我找不到任何提及如何卸载PDF的内容。
关于我应该如何进行的任何想法?我的想法是调用一些外部工具或制作我将使用node-ffi调用的ac / c ++库,但是我必须使用PDF.js来显示以后的PDF状态而且我想我会再遇到同样的问题。