打开具有特定配置的Puppeteer(下载PDF而不是PDF查看器)

时间:2019-05-22 09:58:22

标签: node.js puppeteer

我想打开具有特定配置的Chromium。

我正在寻找配置to activate the following option

设置=>网站设置=>权限=> PDF文档=>“下载PDF文件,而不是在Chrome中自动打开它们”

我在this command line switch page上搜索了标签,但是处理pdf的唯一参数是--print-to-pdf,这与我的需求不符。

您有什么想法吗?

2 个答案:

答案 0 :(得分:3)

没有任何选项可以传递给Puppeteer来强制PDF下载。但是,您可以使用chrome-devtools-protocol添加content-disposition: attachment响应标头来强制下载。

您需要执行的操作的视觉流程:

cdp-modify-response-header (2)

我将在下面提供完整的示例代码。在下面的示例中,PDF文件和XML文件将以headful模式下载。

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: null, 
  });

  const page = await browser.newPage();

  const client = await page.target().createCDPSession();

  await client.send('Fetch.enable', {
    patterns: [
      {
        urlPattern: '*',
        requestStage: 'Response',
      },
    ],
  });

  await client.on('Fetch.requestPaused', async (reqEvent) => {
    const { requestId } = reqEvent;

    let responseHeaders = reqEvent.responseHeaders || [];
    let contentType = '';

    for (let elements of responseHeaders) {
      if (elements.name.toLowerCase() === 'content-type') {
        contentType = elements.value;
      }
    }

    if (contentType.endsWith('pdf') || contentType.endsWith('xml')) {

      responseHeaders.push({
        name: 'content-disposition',
        value: 'attachment',
      });

      const responseObj = await client.send('Fetch.getResponseBody', {
        requestId,
      });

      await client.send('Fetch.fulfillRequest', {
        requestId,
        responseCode: 200,
        responseHeaders,
        body: responseObj.body,
      });
    } else {
      await client.send('Fetch.continueRequest', { requestId });
    }
  });

  await page.goto('https://pdf-xml-download-test.vercel.app/');

  await page.waitFor(100000);

  await client.send('Fetch.disable');

  await browser.close();
})();

有关详细说明,请参阅我设置的带有注释的Git repo。它还包括playwright的示例代码。

答案 1 :(得分:0)

Puppeteer当前不支持导航(或下载)PDF 在无头模式下很容易。引用page.goto函数的文档:

  

注意(无头模式)不支持导航到PDF文档。参见upstream issue

但是,您可以做的是检测浏览器是否导航到PDF文件,然后自己通过Node.js下载。

代码示例

const puppeteer = require('puppeteer');
const http = require('http');
const fs = require('fs');

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();

    page.on('request', req => {
        if (req.url() === '...') {
            const file = fs.createWriteStream('./file.pdf');
            http.get(req.url(), response => response.pipe(file));
        }
    });

    await page.goto('...');
    await browser.close();
})();

这将导航到URL并监视正在进行的请求。如果找到“匹配的请求”,Node.js将通过http.get手动下载文件并将其通过管道传输到file.pdf中。请注意,这是一个最小的工作示例。您想要catch errors when downloading,并且可能还想根据情况使用比http.get更复杂的东西。

未来笔记

将来,可能会有更简单的方法来做到这一点。当puppeteer支持response interception时,您可以简单地force the browser to download一个文档,但是目前不支持此文档(2019年5月)。