html2pdf.js icon indicating copy to clipboard operation
html2pdf.js copied to clipboard

html2pdf.js produces a blank document on iOS

Open chamaliperera512 opened this issue 4 years ago • 21 comments

I'm using html2pdf.js library to produce a dynamically generated report.

It works well on desktop but when I try to output the PDF on iOS the document is blank except for the headers and footers that I added separately.

Below is the code.

`var opt = { margin: [15, 6, 12, 6], filename: '${options.FileName}', image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 2 }, jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }, pagebreak: { mode: ['avoid-all', ['p','li','h1','h3'], 'legacy'] } };

var parentPDF = function(){ var textElem = document.getElementById('printFooter'); textElem.style.display = "none";

var worker = html2pdf().set(opt).from(document.body).toContainer().toCanvas().toImg().toPdf().then(function () {
    var pdfObject = worker.prop.pdf;
    var number_of_pages = pdfObject.internal.getNumberOfPages();
    var pdf_pages = pdfObject.internal.pages;
    var myFooter = "";

    for (var i = 1; i < pdf_pages.length; i += 1) {
        pdfObject.setPage(i);
        pdfObject.setFontSize(8);
        myFooter = "Page " + i.toString() + "/" + (pdf_pages.length-1);
        pdfObject.text(myFooter, 180, 289);
        var textElem = document.getElementById('printFooter');

        if(textElem){
            var text = textElem.textContent;//TODO: get text from HTML
            pdfObject.setFontSize(7);
            pdfObject.text(text, pdfObject.internal.pageSize.getWidth() - 190, 289);
        }
    }

    pdfObject.output('blob');
    window.parent.PDF_CALLBACK(pdfObject.output('blob'));
});

};`

chamaliperera512 avatar Feb 19 '21 05:02 chamaliperera512

@chamaliperera512 Did you able to solve it, I'm also facing the same issue?

rajeshn95 avatar Apr 28 '21 13:04 rajeshn95

@chamaliperera512 @rajeshn95 hey, I faced the same problem, maybe you found any kind of solution?

syrykh-anastasiia avatar Aug 05 '21 09:08 syrykh-anastasiia

@syrykh-anastasiia - No solution, I changed the pdf library to server side

chamaliperera512 avatar Aug 05 '21 23:08 chamaliperera512

@syrykh-anastasiia what is your pagebreak mode? if you are using avoid-all in pagebreak: { mode: ['avoid-all'] }, remove avoid-all and check.

rajeshn95 avatar Aug 06 '21 09:08 rajeshn95

@rajeshn95 - I had same problem and your solution worked for me, but only partially - if you generate a big document, it will still put an empty document. You have other twicks?

CrazyOvi avatar Sep 14 '21 08:09 CrazyOvi

@rajeshn95 - I had same problem and your solution worked for me, but only partially - if you generate a big document, it will still put an empty document. You have other twicks?

@CrazyOvi Empty document as in? where its putting empty document?

rajeshn95 avatar Sep 16 '21 07:09 rajeshn95

Hi @rajeshn95. If I have more then 7 pages on iPhone, it creates the PDF with only header and footer, nothing in the page. If it has less, it creates it correctly. My code is bellow:

// optiunile definite pentru salvarea documentului var opt = { margin: [20, 10, 10, 5], // top, left, bottom, right filename: fileName, image: { type: "jpeg", quality: 0.98, }, html2canvas: { scale: 2, windowWidth: 1024, // dpi: 192, letterRendering: true, }, jsPDF: { unit: "mm", format: "a4", orientation: "landscape", }, pagebreak: { // mode: "avoid-all", // mode: ["avoid-all", "css", "legacy"], // before: ".pageInPDF", // after: ".stepInPDF", }, };

// salvarea documentului in sine var docPDF = html2pdf() .from(pdfBody) .set(opt) .toPdf() .output() .get("pdf") .then((pdf) => { var totalPages = pdf.internal.getNumberOfPages(); for (var i = 1; i <= totalPages; i++) { pdf.setPage(i); pdf.setFontSize(20); pdf.setTextColor(0);

        // facem HEADAER - LOGO
        pdf.addImage(require("../assets/logo.png"), "PNG", 20, 3.5, 20, 10);

        // facem HEADER - TEXT
        pdf.text(45, 10.5, "TASK ANALYSIS");

        // facem FOOTER
        pdf.setFontSize(10);
        pdf.text(10, 205, "PAGE " + i + "/" + totalPages);
      }
    });

  await docPDF
    .outputPdf()
    .then((pdf) => {
      this.sendPDF(btoa(pdf), fileName); // function that sends the info (base64 of PDF and filename) to backend
    })
    .save();

I understand that the problem comes from Safari canvas limitations and creating and adding one page at a time would be the solution - could you help me?

CrazyOvi avatar Sep 18 '21 09:09 CrazyOvi

+1

parvathirajan avatar Feb 18 '22 04:02 parvathirajan

Do you have a solution for this? I have the same problem

Shnrqpdr avatar Apr 20 '22 19:04 Shnrqpdr

Do you have a solution for this? I have the same problem

I will put below the way I did it. Still, I had to ask the user not to create a PDF with more then 10 pages and to pray he/she won't :)

  // options for generated pdf
  var opt = {
    margin: [20, 5, 12.5, 5], // top, left, bottom, right - adauga cate 5 la fiecare daca e nevoie
    filename: fileName,
    image: {
      type: "jpeg", // jpg, jpeg, bmp, png
      quality: 1.0,
    },
    html2canvas: {
      scale: 1.5,
      dpi: 192,
      letterRendering: true,
      windowWidth: "280mm",
      windowHeight: "260mm",
      allowTaint: true,
    },
    jsPDF: {
      unit: "mm",
      // format: "a4",
      format: [260, 280],
      orientation: "landscape", // landscape sau portrait
      compress: true,
    },
    pagebreak: {
      mode: "css",
      // mode: ["avoid-all", "css", "legacy"],
      before: ".break-before",
      after: ".break-after",
      avoid: ".break-avoid",
    },
  };

  // generating the PDF
  var docPDF = html2pdf()
    .from(pdfBody)
    .set(opt)
    .outputPdf()
    .get("pdf")
    .then((pdf) => {
      var totalPages = pdf.internal.getNumberOfPages();
      for (var i = 1; i <= totalPages; i++) {
        pdf.setPage(i);
        pdf.setFontSize(20);
        pdf.setTextColor(0);

        // add HEADAER - LOGO
        pdf.addImage(require("../assets/logo.png"), "PNG", 20, 3.5, 20, 10);

        // add HEADER - TEXT
        pdf.text(45, 10.5, "HEADER TEXT");

        // add FOOTER
        pdf.setFontSize(10);
        pdf.text(
          pdf.internal.pageSize.getWidth() * 0.88,
          pdf.internal.pageSize.getHeight() - 3.5,
          "PAGE " + i + "/" + totalPages
        );
      }
    });

// save PDF
await docPDF.outputPdf().then((pdf) => {
    // send PDF info to function (my function sends the info to may backend api
    this.sendPDF(btoa(pdf), fileName);
    // console.log(fileName, pdf);
  }).save(); // save/download the pdf

I hope this will help you. P.S: play with the options to fit your needs.

CrazyOvi avatar Apr 28 '22 08:04 CrazyOvi

after many ways to solve this problem this config fix it on IOS

  const opt = {
    filename: 'filename',
    image: {
      type: "jpeg",
      quality: 1.0,
    },
    html2canvas: {
      scale: 1.5,
      dpi: 192,
      letterRendering: true,
      allowTaint: true,
    },
    jsPDF: {
      unit: "mm",

      format: [260, 280],
      orientation: "landscape",
      compress: true,
    },
  }

Ahmed-Essam-WasilaDev avatar May 11 '22 07:05 Ahmed-Essam-WasilaDev

For me the fix for iOS was simply to add compress: true. My guess is that iOS can't handle a large render.

coderfin avatar Aug 24 '22 06:08 coderfin

For me the fix for iOS was simply to add compress: true. My guess is that iOS can't handle a large render.

You put this in "options" (opt) ?

CrazyOvi avatar Aug 24 '22 06:08 CrazyOvi

For me the fix for iOS was simply to add compress: true. My guess is that iOS can't handle a large render.

You put this in "options" (opt) ?

jsPDF - as seen in @Ahmed-Essam-WasilaDev's response https://github.com/eKoopmans/html2pdf.js/issues/397#issuecomment-1123306899

coderfin avatar Oct 11 '22 08:10 coderfin

Somehow when the generated pdf is over 1 MB on iphone, it generates a pdf with blank pages

minaramsis93 avatar Jan 31 '23 14:01 minaramsis93

Somehow when the generated pdf is over 1 MB on iphone, it generates a pdf with blank pages

I can confirm that the pages are blank from a certain size. I have an 800kb 6-pager that renders as blank, if i remove the last two pages it works again.

WesleySmits avatar Feb 03 '23 21:02 WesleySmits

Hello all. My project is in vue3 and cordova. In ios when i generate the pdf i see the pdf but i cannot do anything. i cannot go back, i cannot save it. i have to close the application and restart it. any solution?

macgneto avatar Mar 13 '23 16:03 macgneto

Somehow when the generated pdf is over 1 MB on iphone, it generates a pdf with blank pages

I can confirm that the pages are blank from a certain size. I have an 800kb 6-pager that renders as blank, if i remove the last two pages it works again.

Here i could avoid this error in iOS spliting the pages of the pdf to generate one by one and merge them at the final of the process.

``

  const elements = [ ]; // grab your HTML elements and paste here, i use the "id", for example. Doing this, you will create 
                                    // pdf's of  these elements and merge them 

  let worker = html2pdf()
    .set(pdfOptions)
    .from(elements[0]);

  if (elements.length > 1) {
    worker = worker.toPdf();

    elements.slice(1).forEach(async element => {
      worker = worker
        .get('pdf')
        .then(pdf => {
          pdf.addPage();
        })
        .from(element)
        .toContainer()
        .toCanvas()
        .toPdf();
    });
  }

  return worker;

``

Shnrqpdr avatar Mar 13 '23 17:03 Shnrqpdr

Shnrqpdr Thank you! It works!

Igor3007 avatar May 31 '23 08:05 Igor3007

Hi everyone, PDF content blank after download in IOS

var content = document.querySelector('#RCH-pdf'); var opt = { margin: [-10, 0, 5, 0], filename: 'Summary Report.pdf', jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }, pagebreak: { before: ['.audit-block', '.new-items-list', '.block-ops:nth-child(3)', '.block-fs:nth-child(3)', '.block-fs:nth-child(8)', '.block-ops:nth-child(8)', '.block-fs:nth-child(13)', '.block-ops:nth-child(13)', '.block-fs:nth-child(18)', '.block-ops:nth-child(18)', '.block-fs:nth-child(23)', '.block-ops:nth-child(23)', '.block-fs:nth-child(28)', '.block-ops:nth-child(28)', '.block-fs:nth-child(32)', '.block-ops:nth-child(32)', '.block-fs:nth-child(37)', '.block-ops:nth-child(37)', '.block-fs:nth-child(42)', '.block-ops:nth-child(42)', '.block-fs:nth-child(47)', '.block-ops:nth-child(47)', '.block-fs:nth-child(52)', '.block-ops:nth-child(52)', '.block-fs:nth-child(57)', '.block-ops:nth-child(57)', '.block-fs:nth-child(62)', '.block-ops:nth-child(62)', '.block-fs:nth-child(67)', '.block-ops:nth-child(67)'] } }

html2pdf().from(content).set(opt).save();

LMkhitaryan avatar Mar 22 '24 14:03 LMkhitaryan