jsPDF icon indicating copy to clipboard operation
jsPDF copied to clipboard

JsPdf is saving a pdf but takes too long time to show it in google chrome

Open stounej opened this issue 4 years ago • 20 comments

I'm using JsPDF to download an html styled element, but when it is downloaded, it takes too long to be showed in google chrome as pdf (shows just an empty pdf document at first and charge it after long time),

the size of the file is only 300KB, I don't know why I have this problem however it's showed correctly in mozilla firefox browser

Please do you know how could I solve this problem.

this is my code

generatePDF = () => { var doc = new jsPDF('p','pt',"a4"); const inp = document.getElementById("cv"); doc.html( inp , { html2canvas: { scale: 0.75, }, callback: function (doc) { var pageCount = doc.internal.getNumberOfPages(); doc.deletePage(pageCount) doc.save("download.pdf"); } }); }

this is the pdf file: downloaded.pdf

stounej avatar Apr 19 '21 15:04 stounej

Please attach the PDF document.

HackbrettXXX avatar Apr 20 '21 07:04 HackbrettXXX

I have edited my post and included the pdf document, this is the code rendered in the pdf document:

import` '../App.css;
import personalInfo from '../Contexts/personalInfo';
import Grid from '@material-ui/core/Grid';
import {Typography} from '@material-ui/core';
import clsx from 'clsx';
import {makeStyles} from '@material-ui/core/styles';

const useStyles = makeStyles({
  paragraphes: {
    fontSize: "12px",
    overflow: "hidden",
    whiteSpace: "pre-wrap"
  },
  Typography: {
    textAlign: "center"
  },
  title: {
    fontSize: "20px",
    marginTop: "45px",
    textAlign: "center",
    fontFamily: "bold",
    backgroundColor: "#96b0bc",
    color: "white"
  },
  dates: {
    marginTop: "40px",
    fontSize: "12px",
    marginLeft: "13px"
  },
  h4: {
    fontSize: "15px",
    fontWeight: "bold",
    marginBottom: "8px",
    marginTop: "10px"
  }
});

//width: "21cm",height:"29.7cm"{width: "248.0px",height:"350.8px"
function PaperA4() {
  const classes = useStyles();
  return (
    <div class="page" data-size="A4" id="cv">
      <personalInfo.Consumer>
        {({
          fullname,
          email,
          phone,
          address,
          zip,
          city,
          country,
          driving,
          status,
          nationality
        }) => (
          <Grid container xs={12} direction="column" justify="center">
            <Grid
              item
              xs={12}
              justify="center"
              alignItems="center"
              style={{
              lineHeight: "5px",
              marginTop: "20px"
            }}>
              <Typography align="center" variant="h5">{fullname}</Typography>
            </Grid>
            <Grid item xs={12}>
              <Typography className={clsx(classes.Typography, classes.paragraphes)}>
                {email}&nbsp; {phone}&nbsp; {address}
                &nbsp; &nbsp; {city}
                &nbsp; {country}
                &nbsp; {nationality}
                &nbsp; {status}
                &nbsp; {zip}
                &nbsp;{driving}
              </Typography>
            </Grid>

          </Grid>
        )}
      </personalInfo.Consumer>
      <Grid container xs={12} direction="column" justify="center">
        <Typography className={classes.title} variant="h5">Professional Experience
        </Typography>
        <personalInfo.Consumer>
          {({experience}) => (experience.map((exp, i) => {
            return (
              <div key={i}>
                <Grid container xs={12} spacing={false}>
                  <Grid xs={3}>
                    <Typography className={classes.dates}>
                      {exp.startdate}-{exp.enddate}<br/> {exp.city},{exp.country}
                    </Typography>
                  </Grid>
                  <Grid xs={8}>
                    <Typography className={classes.paragraphes}>
                      <Typography className={classes.h4}>
                        {exp.job}
                        <br/> {exp.employer}
                      </Typography>
                      {exp.description}
                    </Typography>
                  </Grid>
                </Grid>
              </div>

            )
          }))}
        </personalInfo.Consumer>
      </Grid>
      <Typography className={classes.title} variant="h5">Education
      </Typography>
      <personalInfo.Consumer>
        {({education}) => (education.map((edu, i) => {
          return (
            <div key={i}>
              <Grid container xs={12} spacing={false}>
                <Grid xs={3}>
                  <Typography className={classes.dates}>
                    {edu.startdate}-{edu.enddate}<br/> {edu.city},{edu.country}
                  </Typography>
                </Grid>
                <Grid xs={8}>
                  <Typography className={classes.h4}>
                    {edu.degree}
                    <br/> {edu.school}
                  </Typography>
                  <Typography className={classes.paragraphes}>
                    {edu.description}
                  </Typography>
                </Grid>
              </Grid>
            </div>

          )
        }))}
      </personalInfo.Consumer>

    </div>

  );
}

export default PaperA4;`

stounej avatar Apr 20 '21 09:04 stounej

The performance issue seems to be that each letter is written as a single chunk of text. Why that is, I don't know, yet.

HackbrettXXX avatar Apr 22 '21 09:04 HackbrettXXX

I tried to transform the document to an Image before saving it and it worked but the text inside the pdf can't be copied, I need the text to be copyable.

stounej avatar Apr 22 '21 12:04 stounej

Seems like if there is letter-spacing in CSS, this will happen. Here is the workaround I am using to remove letter-spacing for PDF:

        onclone: async (d: HTMLDocument) => {
          const styleSheet = `
            * {
              letter-spacing: initial !important;
            }
          `;
          const style = document.createElement('style');
          style.innerText = styleSheet;
          d.head.appendChild(style);
        }

KurtGokhan avatar Jul 26 '21 08:07 KurtGokhan

Any return? have the same issue

kevinmelo avatar Sep 10 '21 17:09 kevinmelo

In addition to letter-spacing, too many words can also cause this issue. When letter-spacing is not 0, each letter is rendered separately. But when it is 0, html2canvas renders each word separately and that still makes the PDF size grow too much and cause performance problems.

I created this PR in html2canvas which significantly improves the performance by rendering multiple words in a line together.

KurtGokhan avatar Oct 01 '21 13:10 KurtGokhan

I have the same problem. The pdf generated from html is loaded very slow by chrome and edge and scrolling is choppy.

CollenZhou avatar Dec 20 '21 05:12 CollenZhou

Hi, @KurtGokhan I've tried the mentioned solution of removing the letter-spacing but it made no difference. The PDF is still extremely choppy on chromium browsers (e.g. Edge is a chromium browser).

DanLopess avatar Dec 20 '21 09:12 DanLopess

@DanLopess

In addition to letter-spacing, too many words can also cause this issue.

One workaround I found is to render the text to an image, and print that into PDF. But text will not be selectable in the PDF if you do that.

KurtGokhan avatar Dec 20 '21 10:12 KurtGokhan

@KurtGokhan Yeah unfortunately that wouldn't be ideal. However if I did that, since my HTML converts into multiple pages the image would have to be split (still haven't figured out how to do that) and I would have to calculate how many pages would be needed.

DanLopess avatar Dec 20 '21 10:12 DanLopess

Hi dear authors any update?

CollenZhou avatar Jan 06 '22 01:01 CollenZhou

Hi, just FYI. I noticed if a single table cell contains too much text will cause the performance issue. Hope it helps.

CollenZhou avatar Jan 07 '22 07:01 CollenZhou

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 08 '22 02:04 github-actions[bot]

Also having the same issue, Any Suggestions guys??

prasheel888 avatar Oct 18 '22 09:10 prasheel888

Also having the same issue, Any Suggestions guys??

At the end the best solution was using Puppeeter with my nodejs backend

kevinmelo avatar Oct 18 '22 10:10 kevinmelo

Also having the same issue, Any Suggestions guys??

At the end the best solution was using Puppeeter with my nodejs backend

Thanks For Suggestion!!

prasheel888 avatar Oct 18 '22 10:10 prasheel888

trying @KurtGokhan css hack does improve the rendering speed a little but when there's Word Starting With Upper Case it will sometimes join 2 word together --> WordWord.

Is there any other workaround ?

haaah avatar Jan 03 '24 03:01 haaah

In my case generated PDF was loading fine in Ubuntu Document Viewer, but not in Chrome PDF viewer. Rendering was slow for some pages, visible especially on scrolling (but also on load if I put problematic element on first page). I could narrow down the issue to border-radius style on my table element. If text was short then there was no issue, but for long texts it was loading very long (forever). I set border-radius to 0 on my table container class and problem disappeared. I do not know why is that. I also played with letter-spacing style and set 0 globally, but it helped just a little I would say - finally border-radius solved the issue.

Html:

<div id="exported-content">
        <div class="table-container">
        <table>
            <tr>
                <td>Test</td>
                <td>
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nibh. Etiam non elit dui. Nullam vel eros sit amet arcu vestibulum accumsan in in leo. Fusce malesuada vulputate faucibus. Integer in hendrerit nisi. Praesent a hendrerit urna. In non imperdiet elit, sed molestie odio. Etiam auctor sit amet odio et luctus. Quisque in massa a libero luctus suscipit. Cras metus purus, iaculis ut aliquam non, varius quis nibh. Quisque a interdum augue. Nam ut nibh mauris.
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nibh. Etiam non elit dui. Nullam vel eros sit amet arcu vestibulum accumsan in in leo. Fusce malesuada vulputate faucibus. Integer in hendrerit nisi. Praesent a hendrerit urna. In non imperdiet elit, sed molestie odio. Etiam auctor sit amet odio et luctus. Quisque in massa a libero luctus suscipit. Cras metus purus, iaculis ut aliquam non, varius quis nibh. Quisque a interdum augue. Nam ut nibh mauris.
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nibh. Etiam non elit dui. Nullam vel eros sit amet arcu vestibulum accumsan in in leo. Fusce malesuada vulputate faucibus. Integer in hendrerit nisi. Praesent a hendrerit urna. In non imperdiet elit, sed molestie odio. Etiam auctor sit amet odio et luctus. Quisque in massa a libero luctus suscipit. Cras metus purus, iaculis ut aliquam non, varius quis nibh. Quisque a interdum augue. Nam ut nibh mauris.
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nibh. Etiam non elit dui. Nullam vel eros sit amet arcu vestibulum accumsan in in leo. Fusce malesuada vulputate faucibus. Integer in hendrerit nisi. Praesent a hendrerit urna. In non imperdiet elit, sed molestie odio. Etiam auctor sit amet odio et luctus. Quisque in massa a libero luctus suscipit. Cras metus purus, iaculis ut aliquam non, varius quis nibh. Quisque a interdum augue. Nam ut nibh mauris.
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nibh. Etiam non elit dui. Nullam vel eros sit amet arcu vestibulum accumsan in in leo. Fusce malesuada vulputate faucibus. Integer in hendrerit nisi. Praesent a hendrerit urna. In non imperdiet elit, sed molestie odio. Etiam auctor sit amet odio et luctus. Quisque in massa a libero luctus suscipit. Cras metus purus, iaculis ut aliquam non, varius quis nibh. Quisque a interdum augue. Nam ut nibh mauris.
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla nec purus feugiat, molestie ipsum et, consequat nibh. Etiam non elit dui. Nullam vel eros sit amet arcu vestibulum accumsan in in leo. Fusce malesuada vulputate faucibus. Integer in hendrerit nisi. Praesent a hendrerit urna. In non imperdiet elit, sed molestie odio. Etiam auctor sit amet odio et luctus. Quisque in massa a libero luctus suscipit. Cras metus purus, iaculis ut aliquam non, varius quis nibh. Quisque a interdum augue. Nam ut nibh mauris.
                </td>
            </tr>
        </table>
        </div>
 </div>

Css:

.table-container {
    border-radius: 8px !important; // !!! This line was causing an issue with rendering PDF in Chrome.
    overflow: hidden;
    background-color: white;
}

JS:

new jsPDF({
            orientation: 'p',
            unit: 'mm',
            format: this.paperFormat,
            putOnlyUsedFonts: true,
            compress: true,
        }).html(document.getElementById('exported-content'), {
            html2canvas: {
                async: true,
                letterRendering: false,
                logging: true,
                removeContainer: true,
            },
            callback: (doc) => {
                doc.save("test.pdf");
            },
            margin: [15, 15, 15, 15],
            autoPaging: true,
            width: 180,
            windowWidth: 1080,
        });

adamturski avatar Feb 28 '24 00:02 adamturski

@adamturski Thank you for the update. I just tested and I reproduce that removing the border radius in my generated pdf make them way faster in chrome.

Amatewasu avatar Feb 28 '24 09:02 Amatewasu