最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Html to Canvas to Base64 to PDF - Stack Overflow

programmeradmin9浏览0评论

So I'm trying to work out a way to convert html to pdf entirely on the clients side, somewhere I read that you can convert a base64 to a pdf on the client side, and from there I remembered you can create a canvas from html and a Base 64 from a Canvas. So I got everything working up until converting the base64 to pdf. I cant seem to get the last part to work. Here is my code

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);

I'm using the html2canvas library to convert the html to canvas and attach it to the body, and so far that works flawlessly. But why cant I convert the base64 to pdf. It just opens a blank page with the url "data:" as if its not loading the base64 string with it. Any help would be appreciated, I might be over thinking this and im sure there is an easier way. Here is a jsfiddle of the problem.

So I'm trying to work out a way to convert html to pdf entirely on the clients side, somewhere I read that you can convert a base64 to a pdf on the client side, and from there I remembered you can create a canvas from html and a Base 64 from a Canvas. So I got everything working up until converting the base64 to pdf. I cant seem to get the last part to work. Here is my code

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);

I'm using the html2canvas library to convert the html to canvas and attach it to the body, and so far that works flawlessly. But why cant I convert the base64 to pdf. It just opens a blank page with the url "data:" as if its not loading the base64 string with it. Any help would be appreciated, I might be over thinking this and im sure there is an easier way. Here is a jsfiddle of the problem.

Share Improve this question edited May 30, 2014 at 18:45 Joe Komputer asked May 30, 2014 at 16:40 Joe KomputerJoe Komputer 1,3453 gold badges12 silver badges25 bronze badges 7
  • Does this help? stackoverflow./questions/11415665/… Or maybe this: stackoverflow./questions/12092633/… ? – blurfus Commented May 30, 2014 at 16:49
  • The first one I have tryed to implement using the base64 transcoder but still get nothing. and the second one looks to be doing the opposite of what im trying to do. It looks like it wants to take a pdf to render the page from my understanding. – Joe Komputer Commented May 30, 2014 at 16:53
  • you are right, the second one is the opposite but I figured the API may lead somewhere. Can you post a fiddle to see how the issue behaves? – blurfus Commented May 30, 2014 at 17:14
  • Are you using cross-domain images? If so you might be causing CORS security violations that causes canvas.toDataURL to fail: html2canvas.hertzen./faq.html – markE Commented May 30, 2014 at 18:11
  • No, everything is being done on localhost, so there is no interaction with the server or other domains. Also the datatourl call is returning a string. It's just not being passed to the window.open call. – Joe Komputer Commented May 30, 2014 at 18:41
 |  Show 2 more ments

1 Answer 1

Reset to default 13 +50

Problem

I guess first off, we'll go through what's wrong with your code I guess. First of all, rather than setTimeout, the "pdf-ing" code should be inside onRendered as potentially, you might find that the code runs before the canvas could be rendered.

Next, how you're prefixing the PDF from the datauri. with a data:application/pdf;base64,. Canvas outputs the full datauri already. For example data:image/PNG;base64,BASE64DATAHERE.... What your're doing is prefixing the data:application/pdf:base64, so it'll look like data:application/pdf:base64,data:image/PNG;base64,BASE64DATAHERE... which is wrong. You need to replace the prefixes pletely. I made a simple demo of this here where I replaced a PNG datauri with jpeg.

Code is

//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

The output should look like

The prefixing one cannot be rendered as it's not a valid base64 image data.

Continuing on, looking at the output, we note that, the image with the jpeg datauri, has transparent background. JPEG can't have transparent background. So in essence, the data is still PNG, and only because lenient renderer that the browser accepts that though it says it's jpeg it's actually still png, and still show it.

This brings us to the final problem with your code. As far as I know, in most cases, you can't actually convert something by just changing the datauri. I tried testing this by manually changing an image datauri to a datauri with pdf prefix. Chrome loaded it's builtin pdf plugin but it "failed to load".


Solution

Looking around there's actually a pdf writer written in javascript:

jsPDF

It has a pdf rendered that you can use and has all sorts of methods that you can look at. As an example, you can create a pdf from a datauri with the .addImage() method. I updated your code to use 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")
  }
});

And it seems to work well.

发布评论

评论列表(0)

  1. 暂无评论