将Html转换为Canvas再转换为Base64最终生成PDF

4

所以我正试图找到一种在客户端完全将html转换为pdf的方法,我在某个地方读到过,您可以在客户端上将base64转换为pdf,然后我记得您可以从html和Canvas的Base 64创建画布。因此,我把所有东西都弄好了,直到将base64转换为pdf。 我似乎无法使最后一部分工作。 这是我的代码:

var element =  document.getElementById('canvas1');
        console.log(element);
if (typeof(element) == 'undefined' || element == null)
{
        html2canvas(document.body, {
  onrendered: function(canvas) {
    document.body.appendChild(canvas);
    $('canvas').attr( 'id', 'canvas1' );
  }
});
    }
    setTimeout(function() {
 canvas = document.getElementById("canvas1");
var jpegUrl = canvas.toDataURL("image/jpeg");
var pngUrl = canvas.toDataURL(); // PNG is the default
console.log("jp"+jpegUrl);
console.log("png"+pngUrl);
window.open("data:application/pdf;base64," + pngUrl);
console.log('new');
},500);

我正在使用html2canvas库将HTML转换为画布并附加到页面上,目前这一步非常顺利。但是,我无法将base64编码转换为PDF格式。它只会打开一个空白页面,URL为"data:",好像没有加载base64字符串。如果有帮助,将不胜感激。也许我想太多了,肯定有更简单的方法。这里是问题的jsfiddle链接。

这个有用吗?https://dev59.com/1mgu5IYBdhLWcg3wUlft 或者也许这个:https://dev59.com/bWct5IYBdhLWcg3wcs-G? - blurfus
我尝试使用base64转码器来实现第一个,但仍然没有得到任何结果。而第二个似乎与我想要做的相反。从我的理解来看,它似乎想要获取PDF以渲染页面。 - Joe Komputer
你是对的,第二个则相反,但我想这个 API 可能会有所帮助。你可以发一个 fiddle 让我们看看问题出在哪里吗? - blurfus
你是否正在使用跨域图像?如果是,可能会导致CORS安全性违规,从而导致canvas.toDataURL失败:http://html2canvas.hertzen.com/faq.html - markE
这是一个jsfiddle,你可能需要启用弹出窗口。 - Joe Komputer
显示剩余2条评论
1个回答

13

问题

首先,我想我们需要审查一下你的代码。首先,不应该使用setTimeout,而是应该将“pdf生成”代码放在onRendered内部,因为有可能会出现代码在画布渲染之前就已经运行的情况。

其次,你在对数据URI的PDF添加前缀时使用了data:application/pdf;base64,。而画布已经输出了完整的数据URI。例如:data:image/PNG;base64,BASE64DATAHERE...。你现在所做的是在data:application/pdf:base64,data:image/PNG;base64,之间添加前缀。这样就会得到一个错误的字符串:data:application/pdf:base64,data:image/PNG;base64,BASE64DATAHERE...。你需要完全替换前缀。我在这里制作了一个简单的演示,用jpeg替换了一个PNG数据URI。

代码如下:

//datauri is an image with a datauri of a png
prefixJpg.src="data:image/jpeg;base64,"+datauri.src
replaceJpg.src="data:image/jpeg;base64,"+datauri.src.substring(22) 
//remove the first 22 characters

输出应该如下所示:

在此输入图像描述

前缀无法呈现,因为它不是有效的base64图像数据。

继续观察输出,我们注意到,具有jpeg datauri的图像具有透明背景。JPEG不能有透明背景。因此从本质上讲,数据仍然是PNG格式,只是由于宽容的渲染器接受浏览器认为它是jpeg,实际上仍然是png,并且仍然显示它。

这带我们来到您的代码的最终问题。据我所知,在大多数情况下,你无法通过改变datauri来转换文件类型。我尝试通过手动将图像datauri更改为pdf前缀的datauri进行测试。Chrome加载了内置的pdf插件,但“未能加载”。


解决方案

查看周围,实际上有一种使用javascript编写的pdf写入程序:

jsPDF

它有一个可以使用的pdf渲染器,并且具有各种方法供您查看。例如,您可以使用.addImage()方法从datauri创建pdf。我更新了您的代码以使用jsPDF

 html2canvas(document.body, {
  onrendered: function(canvas) {
    var pdf = new jsPDF();
    var marginLeft=20;
    var marginRight=20
    pdf.addImage(canvas.toDataURL("image/jpeg"),"jpeg",marginLeft,marginRight)
    window.location=pdf.output("datauristring")
  }
});

看起来它运行良好。


谢谢您的详细解释。不幸的是,对于我的具体问题,pdfJS似乎并不是一个好的解决方案。当使用.fromHTML函数时,pdfJS似乎会忽略所有样式属性,就像您在这里看到的一样:http://jsfiddle.net/8Q582/2/。因此,尽管它确实生成了我想要的pdf文件,但在转换过程中损失了很多东西。 - Joe Komputer
可能有一种方法可以使用.fromHTML,但我猜为了快速修复并回答你的问题,jsPDF(抱歉,我弄错了)有一个addImage()。我会更新我的答案。 - mfirdaus

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