My scenario is:
On clicking a button, import datas on a html into a PDF file.
Since this PDF must have some complicated required style, so my first step is to transfer this page into a image using html2canvas.js and then import this image to a PDF with jsPDF.js
And when the data is too large the PDF must be split to hold all the data,to do this,so I used the codes here: https://github.com/MrRio/jsPDF/pull/397
My problem is: on firefox the splited page on PDF on page 2 or 3...cannot be shown, they are totally blank. but on page 1 it is fine. (this is for firefox)
I tested other browsers they are all fine. pls someone could throw some light on how to fix this?
Here is my plnkr:
http://plnkr.co/edit/ElvAsriK2nssq2U9pgKX?p=preview
function initTemplate(){
datas=getData();
var templateData=_.template($('#tpl').html(), datas);
$('#tplW').html(templateData);
getPDF();
// $('#tplW').append(_.template($('#tpl').html(), datas));
// $('body').html( _.template($('#tpl').html(), datas));
}
function getData(){
var htmlData=$(".MsoNormalTable .inner").find("tr.tablerow");
var datas=[];
$.each(htmlData,function(i,v){
var d=[];
var tds=$(v).find("td");
$.each(tds,function(index,val){
d.push($(val).text());
});
datas.push(d);
});
return datas;
}
function getPDF() {
// initTemplate();
html2canvas($('#tplW')[0], {
onrendered: function(canvas){
canvasToImageSuccess(canvas);
}
});
function canvasToImage (canvas){
var img = new Image();
var dataURL = canvas.toDataURL('image/png');
img.src = dataURL;
return img;
};
function canvasShiftImage (oldCanvas,shiftAmt){
shiftAmt = parseInt(shiftAmt) || 0;
if(!shiftAmt){ return oldCanvas; }
var newCanvas = document.createElement('canvas');
newCanvas.height = oldCanvas.height - shiftAmt;
newCanvas.width = oldCanvas.width;
var ctx = newCanvas.getContext('2d');
var img = canvasToImage(oldCanvas);
ctx.drawImage(img,0, shiftAmt, img.width, img.height, 0, 0, img.width, img.height);
return newCanvas;
};
function canvasToImageSuccess (canvas){
var pdf = new jsPDF('l','px'),
pdfInternals = pdf.internal,
pdfPageSize = pdfInternals.pageSize,
pdfScaleFactor = pdfInternals.scaleFactor,
pdfPageWidth = pdfPageSize.width,
pdfPageHeight = pdfPageSize.height,
totalPdfHeight = 0,
htmlPageHeight = canvas.height,
htmlScaleFactor = canvas.width / (pdfPageWidth * pdfScaleFactor),
safetyNet = 0;
while(totalPdfHeight < htmlPageHeight && safetyNet < 15){
var newCanvas = canvasShiftImage(canvas, totalPdfHeight);
pdf.addImage(newCanvas, 'png', 0, 0, pdfPageWidth, 0, null, 'NONE');
totalPdfHeight += (pdfPageHeight * pdfScaleFactor * htmlScaleFactor);
if(totalPdfHeight < htmlPageHeight){
pdf.addPage();
}
safetyNet++;
}
pdf.save('test.pdf');
};
}
You should use canvas-to-blob and FileSaver.js
and modify this line:
pdf.save('test.pdf');
to this:
var data = pdf.output();
var buffer = new ArrayBuffer(data.length);
var array = new Uint8Array(buffer);
for (var i = 0; i < data.length; i++) {
array[i] = data.charCodeAt(i);
}
var blob = new Blob(
[array],
{type: 'application/pdf', encoding: 'raw'}
);
saveAs(blob, "test.pdf");
You can check it out here.
It worked for me on Mac, Firefox.
I found this solution here.
Related
My code is working correct. It's capturing and generating the whole page and prompting download too. But I need this to be saved on my server automatically in "uploads/pdfs/" folder. I actually want to send this through php mail and save it on the server instead of prompting. Please help me.
This is my script:
function makePDF() {
var quotes = document.getElementById('container-fluid');
html2canvas(quotes, {
onrendered: function(canvas) {
//! MAKE YOUR PDF
var pdf = new jsPDF('p', 'pt', 'letter');
for (var i = 0; i <= quotes.clientHeight/980; i++) {
//! This is all just html2canvas stuff
var srcImg = canvas;
var sX = 0;
var sY = 1278*i; // start 980 pixels down for every new page
var sWidth = 990;
var sHeight = 1278;
var dX = 0;
var dY = 0;
var dWidth = 990;
var dHeight = 1278;
window.onePageCanvas = document.createElement("canvas");
onePageCanvas.setAttribute('width', 990);
onePageCanvas.setAttribute('height', 1278);
var ctx = onePageCanvas.getContext('2d');
// details on this usage of this function:
// https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images#Slicing
ctx.drawImage(srcImg,sX,sY,sWidth,sHeight,dX,dY,dWidth,dHeight);
// document.body.appendChild(canvas);
var canvasDataURL = onePageCanvas.toDataURL("image/png", 1.0);
var width = onePageCanvas.width;
var height = onePageCanvas.clientHeight;
//! If we're on anything other than the first page,
// add another page
if (i > 0) {
pdf.addPage(612, 791); //8.5" x 11" in pts (in*72)
}
//! now we declare that we're working on that page
pdf.setPage(i+1);
//! now we add content to that page!
pdf.addImage(canvasDataURL, 'PNG', 0, 0, (width*.62), (height*.62));
}
pdf.save('output.php')
}
});
}
I am trying to export my chart data consisting of image and data in a PDF. It works fine for me in laptop browser, but while I am trying to do the same in Ipad, the img.onload() function is not firing. I am not sure but I feel like it is due to the size of the image that is rendering in it. Can anybody help me with it? Can we change the pixels of the image that is being rendered?
The code is given below:-
function exportData(exportType) {
if (exportType) {
if (exportType == "pdf") {
alert("clicked pdf")
console.log("pdf export ....")
vm.toggleCanvas = !vm.toggleCanvas;
var canvas = "";
var ctxt = "";
// var img = "";
var sheets = "";
var svgURL = "";
canvas = document.getElementById('canvas');
$log.log($window.screen.width)
//resizing image for PDF
if ($window.screen.width >= 1500) {
canvas.width = $window.screen.width - 150;
} else {
canvas.width = $window.screen.width;
}
console.log("before canvas")
ctxt = canvas.getContext('2d');
sheets = document.styleSheets;
svgURL = generateSVGWithStyling('svg');
// var img = document.createElement('img');
var img = new Image();
console.log("after image")
console.log(img)
alert("imb")
img.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgURL);
img.onload = function () {
debugger
console.log("in load")
alert("in load")
ctxt.drawImage(this, 0, 0);
vm.cnvasImg = "";
vm.cnvasImg = canvas.toDataURL();
var content = "";
console.log("on load")
subExportData(vm.cnvasImg, exportType);
}
console.log(img.src)
} else {
vm.cnvasImg = "nothing";
subExportData(vm.cnvasImg, exportType);
}
}
}
Any help would be apprciated.
Can you please try with passing the width, height properties to Image constructor Object.
var img = new Image(Width, Height);
I have the following JavaScript code https://jsfiddle.net/d72sgwrc/5/ Which suppose to save the image of my screen turn it into Canvas and save it into PDF. Once the file is downloaded on my local machine I am able to view the PDF file within the browser but if I want to open the file on Acrobat PDF viewer I get the following error "There was and error Processing a page. There was a problem readying this document(110). my HTML page is just a table with bunch of generated number.
JS
function exportPDF() {
var pdf = new jsPDF('l', 'px'),
source = $('body')[0];
var canvasToImage = function(canvas) {
var img = new Image();
var dataURL = canvas.toDataURL('image/png');
img.src = dataURL;
return img;
};
var canvasShiftImage = function(oldCanvas, shiftAmt) {
shiftAmt = parseInt(shiftAmt) || 0;
if (!shiftAmt) {
return oldCanvas;
}
var newCanvas = document.createElement('canvas');
newCanvas.height = oldCanvas.height - shiftAmt;
newCanvas.width = oldCanvas.width;
var ctx = newCanvas.getContext('2d');
var img = canvasToImage(oldCanvas);
ctx.drawImage(img, 0, shiftAmt, img.width, img.height, 0, 0, img.width, img.height);
return newCanvas;
};
var canvasToImageSuccess = function(canvas) {
var pdf = new jsPDF('l', 'px'),
pdfInternals = pdf.internal,
pdfPageSize = pdfInternals.pageSize,
pdfScaleFactor = pdfInternals.scaleFactor,
pdfPageWidth = pdfPageSize.width,
pdfPageHeight = pdfPageSize.height,
totalPdfHeight = 0,
htmlPageHeight = canvas.height,
htmlScaleFactor = canvas.width / (pdfPageWidth * pdfScaleFactor),
safetyNet = 0;
while (totalPdfHeight < htmlPageHeight && safetyNet < 15) {
var newCanvas = canvasShiftImage(canvas, totalPdfHeight);
pdf.addImage(newCanvas, 'png', 0, 0, pdfPageWidth, 0, null, 'NONE');
totalPdfHeight += (pdfPageHeight * pdfScaleFactor * htmlScaleFactor);
if (totalPdfHeight < htmlPageHeight) {
pdf.addPage();
}
safetyNet++;
}
pdf.save('test.PDF');
};
html2canvas(source, {
onrendered: function(canvas) {
canvasToImageSuccess(canvas);
}
});
}
exportPDF();
HTML is in JSFiddle as I cant paste it here, I get error https://jsfiddle.net/d72sgwrc/5/
I am using the following JS libraries
https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.debug.js
https://fastcdn.org/FileSaver.js/1.1.20151003/FileSaver.min.js
https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js
https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js
I ran into this same issue. Upgrading to jsPDF 1.3.4 solved it for me.
The version of jspdf debug is very important.
<script src="https://code.jquery.com/jquery-3.1.1.js"></script>
<script src="https://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.debug.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js"></script>
<script src="https://cdn.rawgit.com/MrRio/jsPDF/master/libs/png_support/png.js"></script>
<script src="https://cdn.rawgit.comMrRio/jsPDF/master/plugins/addimage.js"></script>
<script src="https://cdn.rawgit.com/MrRio/jsPDF/master/libs/png_support/zlib.js"></script>
I have had the same issue, I add all parameters of the function.
// Set PDF
let doc = new jsPDF('p', 'mm', [297, 210]);
doc.addImage(dataURL,
"JPEG", marginPDF, 15, widthImgPDF, heigthImgPDF, "fotoX", "SLOW");
doc.save("Fire Inspection - " + questID + ".pdf");
We are building an application where the user can upload images, but I need to resize an image before I can upload them to the server. The input for the file is an input[type=file] and we check if the image is valid. If it is valid, we continue with the following request:
Upload.upload({url: url, data: {file: input.x}, headers: {'Authorization': token}});
The input variable is the value of the input field in the HTML. This codes works great when we don't need to resize the image. Unfortunately, this would only be the case in a perfect world. After a while searching for the same problems, I seem to have found the solution using the following function:
var resize = function(size, url, callback) {
var temp = new Image();
temp.onload = function() {
var target = { width: temp.width, height: temp.height, aspect: temp.width / temp.height };
if (temp.width > temp.height) {
size = Math.min(temp.width, size);
target.width = size; target.height = size / target.aspect;
} else {
size = Math.min(temp.height, size);
target.height = size; target.width = size * target.aspect;
}
var canvas = document.createElement('canvas');
canvas.width = target.width; canvas.height = target.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(this, 0, 0, temp.width, temp.height, 0, 0, target.width, target.height);
callback(canvas.toDataURL(url.split(',')[0].split(':')[1].split(';')[0]));
}; temp.src = url;
}
This appears to be working great. I need to pass a Base64 string. So I wrapped the upload method inside the following:
var reader = new FileReader();
reader.onload = function(e) {
resize(1000, e.target.result, function(done) {
console.log(done);
Upload.upload({url: url, data: {file: done}, headers: {'Authorization': UserService.getToken()}});
});
}
reader.readAsDataURL(file);
This way I pass a Base64 string containing the image and even this seems to be working like a charm. But the biggest problem is, the server expects a real file and not a Base64 string. So the upload itself fails.
I found the function on Convert Data URI to File then append to FormData which should fix this, but it doesn't. I changed the method to this after adding the method from the link:
var reader = new FileReader();
reader.onload = function(e) {
resize(1000, e.target.result, function(done) {
console.log(done);
Upload.upload({url: url, data: {file: dataURItoBlob(done)}, headers: {'Authorization': UserService.getToken()}});
});
}
reader.readAsDataURL(file);
Does any of you know how I could change the Base64 string back to a file again? I found tons of post explaining how I could show them in a browser, but none solving my problem to upload it as file.
Sorry for the question. But it seems the dataURItoBlob function works fine, but there is was no original filename inside the blob, so I couldn't upload it right away. I changed the resize function so it performs both actions at once and this is the result:
var resize = function(size, url, name, callback) {
var temp = new Image();
temp.onload = function() {
var target = { width: temp.width, height: temp.height, aspect: temp.width / temp.height };
if (temp.width > temp.height) {
size = Math.min(temp.width, size);
target.width = size; target.height = size / target.aspect;
} else {
size = Math.min(temp.height, size);
target.height = size; target.width = size * target.aspect;
}
var canvas = document.createElement('canvas');
canvas.width = target.width; canvas.height = target.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(this, 0, 0, temp.width, temp.height, 0, 0, target.width, target.height);
var type = url.split(',')[0].split(':')[1].split(';')[0];
var data = canvas.toDataURL(type);
//callback(data);
var bytes = (data.split(',')[0].indexOf('base64') >= 0) ? atob(data.split(',')[1]) : unescape(dataURI.split(',')[1]);
var ia = new Uint8Array(bytes.length);
for(var i = 0; i < bytes.length; i++) { ia[i] = bytes.charCodeAt(i); }
var blb = new Blob([ia], {type : type});
blb.name = name;
callback(blb);
}; temp.src = url;
};
To upload the file, I do the following:
var deferred = $q.defer();
var reader = new FileReader();
reader.onload = function(e) {
resize(maxSize, e.target.result, image.name, function(done) {
deferred.resolve(Upload.upload({url: url, data: {file: done}, headers: {'Authorization': token}));
});
}
reader.readAsDataURL(image);
return deferred.promise;
I am using PDF.js framework to render PDF. I am using base64 data to render PDF. But in IE 11 pdf looking blurry.
See below screen from IE 11
See below code :
var renderPDF = function(url, canvasContainer,data) {
var scale= 0.9; //"zoom" factor for the PDF
function renderPage(page) {
var canvas = document.createElement('canvas');
var viewport = page.getViewport(scale);
var ctx = canvas.getContext('2d');
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
canvas.height = viewport.height;
canvas.width = viewport.width;
canvasContainer.appendChild(canvas);
page.render(renderContext);
}
function renderPages(pdfDoc) {
for(var num = 1; num <= pdfDoc.numPages; num++)
pdfDoc.getPage(num).then(renderPage);
}
PDFJS.disableWorker = false;
var pdfAsDataUri = "data:application/pdf;base64,"+data; // shortened
var pdfAsArray = convertDataURIToBinary(pdfAsDataUri);
PDFJS.getDocument(pdfAsArray).then(renderPages);
};
var BASE64_MARKER = ';base64,';
var convertDataURIToBinary = function(dataURI) {
var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
var base64 = dataURI.substring(base64Index);
var raw = atob(base64);
var rawLength = raw.length;
var array = new Uint8Array(new ArrayBuffer(rawLength));
for(var i = 0; i < rawLength; i++) {
array[i] = raw.charCodeAt(i);
}
return array;
};
Please help me.
If your PDF.js isn't working in your IE11 it requires compatibility.js.
You can insert the following line to your code right after the tag (before any other <script>s):
<script type="text/javascript" src="../../web/compatibility.js"></script>
You can also add file below:
metadata.js
bidi.js
Hope it help.
Thats the code for PDF.js framework... i would do is to check if IE10 works OK... if not!!! then your code have some stuff than cannot create from the right way... PDF.js that you can validate. (validate on IE11) then is not framework issue.
Other issue could be that some characters are not OK!! could you post your var "data"???
Regards!!!