Friday, May 10, 2024
 Popular · Latest · Hot · Upcoming
29
rated 0 times [  30] [ 1]  / answers: 1 / hits: 33939  / 10 Years ago, fri, may 30, 2014, 12:00:00

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.


More From » html

 Answers
32

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 completely. 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



enter



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.


[#70786] Thursday, May 29, 2014, 10 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
tierney

Total Points: 45
Total Questions: 101
Total Answers: 94

Location: Sudan
Member since Thu, May 7, 2020
4 Years ago
;