使用jspdf创建的PDF文件大小过大

44

我正在使用jspdf在浏览器内创建PDF。我有多个图表,其中包含svg作为图表数据。为了向pdf添加数据,我使用canvas将svg转换为png,然后使用canvas.toDataURL方法转换为Base64数据。在进行所有这些转换之后,由jspdf创建的文件大小很大(约50 MB)。 以下是图表数据和画布的div的代码。

newdiv = document.createElement("div");
newdiv.className = "big_Con_graph big_Con_graph0";
newdiv.style.height = "0px";
newdiv.id = "big_Con_graph" + id;

以下是SVG图表加载的尺寸。

document.getElementById("big_Con_graph" + id).style.display = "block";
var big_chartReference = FusionCharts("big_myChartId"+id);
if(big_chartReference != null){
    big_chartReference.dispose();
}
var big_width = "1088";
var big_height = "604";

现在以下是将上面的图形SVG数据转换并添加到PDF中的代码。

var elem_graph = $($('.big_Con_graph,big_Con_graph0')[count]).clone(true);
svgString = $(elem_graph).find("span").html();
var img = document.createElement('img');
var DOMURL = self.URL || self.webkitURL || self;
var svg = new Blob([svgString], {type: "image/svg+xml;charset=utf-8"});
var url = DOMURL.createObjectURL(svg);
img.onload = pdfAfterImageLoad(img,pdf,imgLoadSequence,DOMURL,totalReports,reportName);
img.src = url;

这是PDFAfterImageLoad函数的代码:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var png = canvas.toDataURL("image/png");
pdf.addImage(png, 'PNG', leftmargin, 120, 485, 270);

我正在使用png格式,所以不能使用imagequality参数。

有人能帮我减小文件大小吗?


你是将其转换为base64吗?因为jspdf需要这样做吗? - YakovL
我没有在我的端存储图像,通过点击按钮获取SVG数据并通过画布将其转换为PNG,因此整个过程需要Base64数据。即使我不能将所有图形数据存储在客户端存储中。 - Asha Koshti
我明白了。那你为什么使用 PNG 而不是 JPEG 呢?使用带有质量修饰符的 JPEG 可以帮助你(请参见 https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL)。 - YakovL
1
这个图片的尺寸是多少?你能展示一下这张图片包含什么吗?它适用于你添加的任何图片吗?你能展示一下添加到jspdf中所使用的代码吗?(而且你的onload回调函数使用方式不正确,应该是一个函数引用;现在它是使用该回调函数返回结果进行调用)。 - user1693593
我认为你需要使用 image/jpeg 格式,并测试可能和适合的质量参数! - Rayon
显示剩余3条评论
6个回答

99

你需要压缩生成的PDF中的图片。尝试使用Deflate.js和adler32cs.js,并在你使用的jsPDF和addImage函数中使用compress参数。例如:

var doc = new jsPDF('p', 'pt','a4',true);

请确保将最后一个参数设置为“true”,参考:https://github.com/MrRio/jsPDF/blob/ddbfc0f0250ca908f8061a72fa057116b7613e78/jspdf.js#L146

仔细查看代码,您会发现最后一个参数是用于启用压缩的。

同时使用:

pdf.addImage(png, 'PNG', leftmargin, 120, 485, 270,'','FAST');

代替

pdf.addImage(png, 'PNG', leftmargin, 120, 485, 270);

您可以在 NONE、FAST、MEDIUM 和 SLOW 中选择其中之一,选择最适合您的。


无论如何,横线没有打印在纸上。 - Shalini
我正在根据自定义图形创建PDF。我可以使用jspdf生成PDF。但是,web页面上的图形颜色和字体颜色会在PDF中复制。(图形缺少box-shadow效果,看起来模糊)。我该如何修复这个问题? - Curious Developer
@HemantKumar,你能给我带上jsfiddle的链接吗?这样我就可以指导你解决问题了。实际上,生成图表的SVG会产生问题,我们需要消除一些标签或进行修正。 - Asha Koshti
这个不起作用,在Edge和Firefox中测试过,添加压缩也没有改变,我没有使用node.js。 - Daniel
1
嗨@Daniel,我敢肯定OP也没有使用node.js。至于提供的解决方案,它适用于帖子中提到的场景,即使用addImage()中的压缩来减小png的大小。如果您遇到了不同的问题并且正在使用jpeg,请像其他解决方案中建议的那样使用压缩。只需注意,使用jpeg进行压缩会导致图像质量差,但会大大降低pdf文件大小。 - hkm93
显示剩余4条评论

23

如果您要将多个图片添加到一个文档中,请使用

pdf.addImage(png, 'PNG', leftmargin, 120, 485, 270, undefined,'FAST');

pdf.addImage(png, 'PNG', leftmargin, 120, 485, 270,'','FAST');
否则,第一张图片将替代所有其他图片。

是的,这只是一个示例。pdf.addImage(png, 'PNG', leftmargin, 120, 485, 270, undefined,'FAST'); 在其中的undefined参数中,每次添加图像时都必须指定不同的名称。根据API,它是别名,每个图像的别名必须是唯一的。 - Asha Koshti
1
只是想说,上面的例子也将我的4Mb PDF(11页,每页10个图表)压缩到了977kb。非常感谢这个提示! - JasonMHirst
我尝试了doc.addImage(imgData, "JPEG", 140, 15, 300, 300, "alias1", undefined, 'SLOW');但是我遇到了错误Uncaught Error: getJpegSize无法找到图像的大小。 - Naren Verma

4
非常好。使用优质的图像降低PDF大小,从90MB变成了3MB。 pdf.addImage(png, 'PNG', 0, 0, 485, 270, undefined,'FAST');

请详细说明您的答案,我在原帖中没有看到任何var pdf - jalsh

1
在我的情况下,使用压缩参数并没有起作用。因此,我使用以下函数自行调整了当前图像的大小:
function resizeBase64Img(base64, width, height) {
    var canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
    var context = canvas.getContext("2d");
    var deferred = $.Deferred();
    $("<img/>").attr("src", "data:image/gif;base64," + base64).load(function() {
        context.scale(width/this.width,  height/this.height);
        context.drawImage(this, 0, 0); 
        deferred.resolve($("<img/>").attr("src", canvas.toDataURL()));               
    });
    return deferred.promise();    
}

并按以下方式调用:

//select my image in base64
var imageStr64 = "/9j/4RiDRXhpZgAATU0AKgA...";
//resize image, add image and create the pdf
resizeBase64Img(imageStr64, 1000, 1000).then(function(newImg){
    doc.addImage($(newImg).attr('src'), 15, 90, 180,180);
    doc.save('mypdf.pdf');
});

你可以在resizeBase64Img函数中使用“width”和“height”参数来生成质量更好或更差的图像质量较高的PDF文件。

0

你尝试过canvg吗?它不太可能减小文件大小,但至少你可以尝试一下。

这个回复中查看片段。


是的,我已经在IE和Safari浏览器中使用canvg了。但它与任何文件大小减小有关。 - Asha Koshti

0

我尝试了使用compress参数并按建议将compression:'MEDIUM'传递给addImage方法,但没有任何反应。

对我有用的是将画布转换为DataUrl base64字符串并传递压缩值。

pdf.addImage({ imageData: canvas.toDataURL('image/jpeg', 0.6),format: 'JPEG', x: 2, y: 100, width: newImageWidth, height: newImageHeight});

在将图像添加到PDF之前,可以对其进行压缩处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接