jsPDF icon indicating copy to clipboard operation
jsPDF copied to clipboard

jsPDF.html output very large fields in document.

Open PierreOlivierMorin opened this issue 4 years ago • 20 comments

Hello there, i've been trying the jsPDF.html function, but it seems its outputting the html but in such large scale that it is unreadable. Am I doing something wrong? I've been using the lines from the documentation itself in my componnent. I am actually working with vue.js.

methods: {
  download() {
    var html = 
    `<body>
      <h1>This is Title</h1>
      <div>
          <p>this is test no.1</p>
      </div>
      <div>
          <p><b>This is test no.1</b></p>
      </div>
      <div>
          <p>This is test no.3</p>
      </div>
    </body>`;
    var doc = new jspdf();
    doc.html(html, {
      callback: function (doc) {
        doc.save();
      },
    });
  },
},

The code results its this file: generated.pdf

PierreOlivierMorin avatar Aug 28 '20 17:08 PierreOlivierMorin

+1

Alexandre-Perron avatar Aug 28 '20 19:08 Alexandre-Perron

try to add options - new jsPDF('p', 'pt', 'a4');. @HackbrettXXX the default unit should be 'pt' instead of 'mm'?!

kakugiki avatar Aug 29 '20 18:08 kakugiki

@kakugiki I agree that "mm" is not a good default. But changing the default is a breaking change, so we shouldn't change it.

HackbrettXXX avatar Aug 31 '20 07:08 HackbrettXXX

@kakugiki Thanks! that worked, but it did not fix the problem of line return, as you can see in the pdf, all words are separated into different lines. Am I still doing something wrong? generated.pdf

PierreOlivierMorin avatar Aug 31 '20 15:08 PierreOlivierMorin

@PierreOlivierMorin looks like a style issue. add a backgroundColor and check the output content.

kakugiki avatar Aug 31 '20 16:08 kakugiki

@kakugiki Thanks! that worked, but it did not fix the problem of line return, as you can see in the pdf, all words are separated into different lines. Am I still doing something wrong? generated.pdf

See my comment in the related issue

Lightras avatar Sep 21 '20 10:09 Lightras

This issue is stale because it has been open 90 days with no activity. It will be closed soon. Please comment/reopen if this issue is still relevant.

github-actions[bot] avatar Dec 21 '20 02:12 github-actions[bot]

I am also facing the same issues. I am using the below code.

var mainlogo = $('.site-header__logo img').attr('src');
var cataglugeName 	= $('.product-single__title').text();
const  footerlogo 	= 'http://example.com/images/footer-logo.png';
const  linedraw 	= 'http://example.com/images/linedraw.png';
var productImage 	= $('.zoomImg').attr('src');

var footerTitle 	= $('.site-footer__item-inner--text .h4').text();
var footerAddress 	= $('.site-footer__rte').text();
// get static content and from translation
var job 			= ($('#app_job').text() != '' ? $('#app_job').text(): 'Job');
var designer 		= ($('#app_designer').text() != '' ? $('#app_designer').text(): 'Designer');
var fixtype 		= ($('#app_fixtype').text() != '' ? $('#app_fixtype').text(): 'Fix Type');
var approved 		= ($('#app_approvedby').text() != '' ? $('#app_approvedby').text(): 'Aproved By');
var room 			= ($('#app_room').text() != '' ? $('#app_room').text(): 'Room');
var date 			= ($('#app_date').text() != '' ? $('#app_date').text(): 'Date');

const doc = new jsPDF();
//console.log('Generate job...'+job);
//console.log('Generate Pdf...'+mainlogo+' title '+cataglugeName+' prod '+productImage+' address '+footerAddress);
// add top header logo 
toDataURL(footerlogo, function(footerlogoDataUrl) {
		//console.log('Footer logo :', footerlogoDataUrl);
	var footerlogoext = get_url_extension(footerlogo);
	doc.addImage(footerlogoDataUrl, footerlogoext, 73, 10,  60, 40,'header','FAST'); // x, y , width, height, alias, mode
});
// add product sheet title below logo 
toDataURL(mainlogo, function(mainLogoDataUrl) {
		//console.log('Logo:', mainLogoDataUrl);
	var mainlogoext = get_url_extension(mainlogo);		
	doc.addImage(mainLogoDataUrl, mainlogoext, 30, 70,  50, 15,'logo','FAST');   // x, y , width, height, alias, mode
	doc.text(cataglugeName, 145,80, null, null, "center");    // // x, y , width, height, mode
});
// add line daraw image below product iamge
toDataURL(linedraw, function(linedrawDataUrl) {
	var linedrawext = get_url_extension(linedraw);
	doc.addImage(linedrawDataUrl, linedrawext, 30, 165,  60, 40,'linedraw','FAST'); // x, y , width, height, alias, mode		
});						
// add product image 
toDataURL(productImage, function(productDataUrl) {			
	//console.log('Logo:', productDataUrl);
	var productimageext = get_url_extension(mainlogo);
	doc.addImage(productDataUrl, productimageext, 18, 90,  80, 80,'product','FAST');
	// get product description
	/*var dimention = $('.product-single__description #app_dimention').text();
	var description = $('.product-single__description #app_description').text();
	doc.text(dimention, 125, 100, null, null, "center");
	var splitDesc = doc.splitTextToSize(description, 100); // used to wrap the description content 
	doc.text(90, 120, splitDesc); */
	
	//doc.rect(18, 18, doc.internal.pageSize.width - 40, doc.internal.pageSize.height - 40, 'S'); // draw a border in pdf
	doc.rect(10, 55, doc.internal.pageSize.width - 18, doc.internal.pageSize.height - 90, 'S'); // draw a border in pdf
	
	// add job input fields 
	var TextField = jsPDF.AcroForm; 
	doc.text(job+":", 30, 225);
	var textField = new doc.AcroFormTextField();
	textField.Rect = [50, 218, 35, 10];
	textField.multiline = false;
	//textField.value ="Job Name"; //
	textField.fieldName = "jobname";
	doc.addField(textField);
	// add designer input fields 		
	doc.text(designer+":", 90, 225);
	var textField = new doc.AcroFormTextField();
	textField.Rect = [130, 218, 35, 10];
	textField.multiline = false;
	textField.fieldName = "designer";
	doc.addField(textField);
	// add fix type input fields 
	var TextField = jsPDF.AcroForm; 
	doc.text(fixtype+":", 30, 240);
	var textField = new doc.AcroFormTextField();
	textField.Rect = [50, 233, 35, 10];
	textField.multiline = false;
	//textField.value ="Job Name"; //
	textField.fieldName = "fixtype";
	doc.addField(textField);
	// add approved by input fields
	doc.text(approved+":", 90, 240);
	var textField = new doc.AcroFormTextField();
	textField.Rect = [130, 233, 35, 10];
	textField.multiline = false;
	textField.fieldName = "approvedby";
	doc.addField(textField);
	// add room input fields 
	var TextField = jsPDF.AcroForm; 
	doc.text(room+":", 30, 255);
	var textField = new doc.AcroFormTextField();
	textField.Rect = [50, 248, 35, 10];
	textField.multiline = false;
	//textField.value ="Job Name"; //
	textField.fieldName = "room";
	doc.addField(textField);
	// add date input fields
	doc.text(date+":", 90, 255);
	var textField = new doc.AcroFormTextField();
	textField.Rect = [130, 248, 35, 10];
	textField.multiline = false;
	textField.fieldName = "date";
	doc.addField(textField);
	
	doc.setFontSize(15);
	doc.text(footerTitle, 100, 275, null, null, "center");
	
	var splitFooter = doc.splitTextToSize(footerAddress, 180); // used to wrap the description content 
	doc.text(splitFooter, 20,275, {align: "justify"});			
	//doc.text(40, 275, splitFooter);
	//doc.text(footerAddress, 80, 275, null, null, "center");
	// current date
	//var myDate = new Date();
	// render html of product description
	//var renderHtml = $('.product-single__description').html();
		// working html render
	doc.html($('.product-single__description').get(0), {
			callback: function () {
		window.open(doc.output('bloburl')); // to debug
			},
			x: 100,
			y: 90,
			margin: [50, 50, 40, 50] // [left, bottom, right, top]
	});
	//window.open(doc.output('bloburl'));
	//doc.save("Product-"+Date()+".pdf"); // will save the file in the current working directory						
});

Here is the PDF generating Generated PDF testPdf.pdf

kantsverma avatar Dec 24 '20 09:12 kantsverma

Solved the issues by adding this by adding wrapper div and css width in px. It work for me

var getContent = "<div style='font-size:11px; border:1px solid; background-color: rgb(239 240 240); padding: 05px 15px; width:300px;'>"+$('.description').html()+"</div>";

doc.html(getContent, {
callback: function () {
 window.open(doc.output('bloburl')); // to debug
},
x: 265,
y: 130
});	

kantsverma avatar Jan 12 '21 13:01 kantsverma

This issue is stale because it has been open 90 days with no activity. It will be closed soon. Please comment/reopen if this issue is still relevant.

github-actions[bot] avatar Apr 13 '21 01:04 github-actions[bot]

Facing same issue. Looking for solution.

neeraj2018 avatar May 23 '21 19:05 neeraj2018

Users should specify PDF as regular 'letter' size and use 'px' scaling with px_scaling fix

ericjames avatar May 29 '21 01:05 ericjames

thanks

neeraj2018 avatar May 30 '21 16:05 neeraj2018

This issue still persists...

lvilca-tekton avatar Jun 04 '21 17:06 lvilca-tekton

You should specify some options. For example i am using const doc = new jsPDF('p', 'px', 'a3', true); while my content is set to width of 500px (centered). This is work for me perfectly. You should look at jsPDFOptions (Image Below) and just play with it. Only tricky option is format. format - It's default page format. It can be "a3", "a4" (default), "a5", "letter", "legal". and also format can take array of 2 numbers ex: [2, 5]. you can look here for this - https://stackoverflow.com/questions/23104008/where-to-change-default-pdf-page-width-and-font-size-in-jspdf-debug-js image

shizzystical avatar Jun 04 '21 23:06 shizzystical

I was using Puppeteer to generate PDF from HTML and file size with 10 png images where 300 Kb. I had to find another solution that works from the client-side so used jsPDF. Now the same HTML generates a PDF of size 23 Mb. Below is my code, Since I am using the compress option it's 23 MB, if not 26 MB. All my PNGs are altogether not even 1 MB. PDF is generated perfectly. Good results except for the large size!!

const doc = new jsPDF({ compress: true });
        doc.setDisplayMode(1);        
        doc.html(html, {
          callback: function (doc) {
            doc.save(
              `${process.env.REACT_APP_NAME}_${new Date().toTimeString()}`
            );
            setMode("html");
            dispatch(hideLoaderUI());
          },
          x: 0,
          y: 0,
          html2canvas: { scale: 0.25 },
        });

A surprising fact is when I used pt as a unit, 9 page PDF became 4 pages [Zoomed out] and still, the size was the same.

Looks like the images are causing the issue. I removed all the images and the PDF became 200 KB. My HTML has base64 png images. Enabled 1 image which shows 32 Kb on the disk, and the PDF size shoot to 3800+ KB. Why?

are you upscaling the image or add something with the image?

sanishtjppi avatar Jul 16 '21 16:07 sanishtjppi

@sanishtjppi There is a bug/missing feature, where images are included in a raw, uncompressed way when using the HTML function. See #3178.

HackbrettXXX avatar Jul 19 '21 08:07 HackbrettXXX

I Solved! Sorry my english, but my soluction was put my element html (a string, really), into a div with style/width in my doc.html. I use template string for this. That's a example. I hope this helps!

doc.html(<div style="width:1350px">${MYELEMENTHTML}</div> (...)

contatofabiofg avatar Jul 04 '22 14:07 contatofabiofg

@kakugiki Thanks! that worked, but it did not fix the problem of line return, as you can see in the pdf, all words are separated into different lines. Am I still doing something wrong? generated.pdf

See my comment in the related issue

Adding width and windowWidth should fix the problem

hezhu-ls avatar Aug 31 '22 18:08 hezhu-ls

try to add options - new jsPDF('p', 'pt', 'a4');. @HackbrettXXX the default unit should be 'pt' instead of 'mm'?!

I tried this. The content does look smaller but it output with many line break

kimheaks avatar Jan 06 '24 08:01 kimheaks