Puppeteer PDF генерирует пустые страницы из облака, работает с почтальоном. Какие-нибудь мысли? - PullRequest
0 голосов
/ 29 января 2020

Я провел дни в поисках, настройках, развертывании, регистрации ... Ничего не помогло. Я надеюсь, что это просто глупое упущение с моей стороны, и тот, кто не похоронен в этом проекте, может просто указать мне на это.

Я пытаюсь использовать Puppeteer для создания PDF из Node.js Express Конечная точка API, размещенная с Firebase Cloud Functions в качестве микросервиса для внешнего интерфейса Vue приложения. Я использую Ax ios для отправки запроса и передаю строку HTML в теле. С помощью bodyparser я могу присвоить данные переменной.

const express = require('express');
const functions = require('firebase-functions');
const puppeteer = require('puppeteer');
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express();

const corsConfig = {
    origin: true,
    credentials: true,
}

app.use(cors(corsConfig));
app.options('*', cors(corsConfig));

app.all('*', async (request, response, next) => {
    response.locals.browser = await puppeteer.launch({
        dumpio: true,
        headless: true,
        args: ['--no-sandbox', '--disable-setuid-sandbox']
    });
    next();
});

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.post('/pdf', async (request, response) => {
    const html = request.body.html;

    //console.log(typeof html, html);

    if (!html) {
        return response.status(400).send(
            'Something happened so I cannot create your PDF right now.');
    }

    const browser = response.locals.browser;
    const page = await browser.newPage();

    //await page.goto(`data:text/html,${encodeURIComponent(html)}`, { waitUntil: 'networkidle0' });

    await page.setContent(html, { waitUntil: ['domcontentloaded', 'load', "networkidle0"] }, { timeout: 0 });
    await page.addStyleTag({ path: 'style.css' });

    const pdf = await page.pdf({
        format: 'Letter',
        printBackground: true,
    });

    //console.log(pdf);
    response.set({ 'Content-Type': 'application/pdf', 'Content-Length': pdf.length });
    response.send(pdf);

    await browser.close();

    return pdf;
});

const opts = { memory: '2GB', timeoutSeconds: 60 };
exports.pdf = functions.runWith(opts).https.onRequest(app);

Запись в консоли показывает, что переменная является строкой, и разметка выглядит хорошо. Когда я использую его для page.setContent(html, {waitUntil: 'networkidle0'}), а затем page.pdf(), я получаю PDF с 3 пустыми страницами. Снимок экрана журнала функций

Я испробовал целую вещь page.goto и те же результаты. Если я изменю строку HTML на что-то намного более короткое, например '<h1>Hello World</h1>' (пробовал как переменную, так и фактическую строку), я получу PDF с 1 пустой страницей. Это заставляет меня верить, что оно понимает меня, а не рендеринг. Я изменил все идентификаторы на класс, а шестнадцатеричные цвета на RGB, чтобы избежать # конфликтов (я читал, что они могут все испортить).

Я пытался использовать шаблон руля и отправлять только JSON данные в тело запроса, и это тоже не сработало. Теперь, если я использую почтальон и отправляю запрос со строкой HTML в теле, я получаю именно то, что ищу. Недостатком этого является то, что у меня нет фрагментов AX IOS, чтобы я мог использовать и копировать результаты в моем приложении.

Вот интерфейс

savePDF() {
      this.getPDF()
        .then(response => {
          const blob = new Blob([response.data], { type: "application/pdf" });
          const link = document.createElement("a");
          link.href = window.URL.createObjectURL(blob);
          link.target = "_blank";
          link.click();
        })
        .catch(err => alert(err));
    },

    async getPDF() {
      const html = document.querySelector(".wrapper").outerHTML;

      axios.defaults.withCredentials = true;

      const pdf = await axios
        .post("MYENDPOINTURL/pdf", { html })
        .then(
          response => {
            return response;
          },
          error => {
            alert(error);
          }
        );
      return pdf;
    }

ОБНОВЛЕНИЕ Я бросил Ax ios и использовал запрос на извлечение сообщений ... и это сработало! После этого я изменил функции интерфейса getPDF и savePDF (на стороне сервера остались прежними) для этого:

async savePDF() {
      const html = document.querySelector(".wrapper").outerHTML;
      var myHeaders = new Headers();
      myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
      var urlencoded = new URLSearchParams();
      urlencoded.append("html", html);
      var requestOptions = {
        method: "POST",
        headers: myHeaders,
        body: urlencoded,
        redirect: "follow"
      };

      fetch("MYENDPOINTURL/pdf", requestOptions)
        .then(response => response.blob())
        .then(result => {
          const blob = new Blob([result], { type: "application/pdf" });
          const link = document.createElement("a");
          link.href = window.URL.createObjectURL(blob);
          link.target = "_blank";
          //link.download = `${this.propertyInfo.property}-${this.propertyInfo.workType}.pdf`;
          link.click();
        })
        .catch(error => alert("error", error));
    }

1 Ответ

0 голосов
/ 30 января 2020

Мне все равно было бы интересно, чтобы Ax ios работал, но отключил его для извлечения, и теперь все в порядке.

const html = document.querySelector(".wrapper").outerHTML;
      var myHeaders = new Headers();
      myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
      var urlencoded = new URLSearchParams();
      urlencoded.append("html", html);
      var requestOptions = {
        method: "POST",
        headers: myHeaders,
        body: urlencoded,
        redirect: "follow"
      };

      fetch("MYENDPOINTURL/pdf", requestOptions)
        .then(response => response.blob())
        .then(result => {
          const blob = new Blob([result], { type: "application/pdf" });
          const link = document.createElement("a");
          link.href = window.URL.createObjectURL(blob);
          link.target = "_blank";
          //link.download = `${this.propertyInfo.property}-${this.propertyInfo.workType}.pdf`;
          link.click();
        })
        .catch(error => alert("error", error));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...