D
D
Dmitry Esin2020-01-10 17:31:21
Google Chrome
Dmitry Esin, 2020-01-10 17:31:21

How to make "snapshot to pdf" page of react-spa application correctly?

The client uses a react application with client-side rendering.
The server implements route processing on nodejs express with the logic of generating a page into a pdf file using puppeteer.
The problem is that only the 1st page of the document will get into the pdf and it looks as if only the visible area is saved in the pdf.
I tried to take a picture of the film search page in this way - everything is ok, the whole document gets into the pdf, in pdf it's all divided into 15 pages. But only one sheet of the page gets into the pdf of my application. The rest of the scroll is cut off.
There is an assumption that the problem is related to the implementation of react components (virtual scrolls, infinite lists, graphics on canvas, etc.).
Help, please, with the correct implementation.

const express = require("express");
const morgan = require("morgan");
const cors = require("cors");
const puppeteer = require("puppeteer");

const app = express();
const PORT = process.env.PORT || 3005;

const printPdf = async (projectId, reportName) => {
  const browser = await puppeteer.launch({
    headless: true
  });

  const page = await browser.newPage();

  page.setViewport({
    width: 1920,
    height: 1080
  });

  page.goto(
    `http://localhost:3000/project/${projectId}/report/${reportName}`,
    { waitUntil: "networkidle2" }
  );

  await page.waitForNavigation();
  await page.type("#username", process.env.USERNAME);
  await page.type("#password", process.env.PASSWORD);
  await page.click("#submit");
  await page.waitForSelector(".content", { visible: true });

  const pdfFile = await page.pdf({
    format: "A4",
    printBackground: true
  });

  await browser.close();

  return pdfFile;
};

app.use(cors());
app.use(morgan("combined"));

app.get("/export", function(req, res) {
  const { projectId, reportName } = req.query;

  printPdf(projectId, reportName)
    .then(pdf => {
      res.set({
        "Content-Type": "application/pdf",
        "Content-Length": pdf.length
      });

      res.send(pdf);
    })
    .catch(error => {
      console.log("!!ERROR", error);
    });
});

app.listen(PORT, () => {
  console.log("Server running on port %d", PORT);
});

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Aetae, 2020-01-12
@Aetae

Without looking, you can say that your application is running in window mode 100% by 100%, and all the scrolls that are there are somewhere inside.
I guess the height in setViewport needs to be set a little more so that everything fits.)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question