使用特定配置打开 Puppeteer(下载 PDF 而不是 PDF 查看器)
Posted
技术标签:
【中文标题】使用特定配置打开 Puppeteer(下载 PDF 而不是 PDF 查看器)【英文标题】:Open Puppeteer with specific configuration (download PDF instead of PDF viewer) 【发布时间】:2019-10-08 18:51:51 【问题描述】:我想使用特定配置打开 Chromium。
我正在寻找配置to activate the following option:
设置 => 站点设置 => 权限 => PDF 文档 => “下载 PDF 文件而不是在 Chrome 中自动打开它们”
我在this command line switch page 上搜索了标签,但处理pdf 的唯一参数是--print-to-pdf
,这不符合我的需要。
你有什么想法吗?
【问题讨论】:
【参考方案1】:没有选项可以传递给 Puppeteer 来强制下载 PDF。但是,您可以使用 chrome-devtools-protocol 添加 content-disposition: attachment
响应标头来强制下载。
您需要做的事情的可视化流程:
我将在下面包含一个完整的示例代码。在下面的示例中,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();
)();
更详细的解释请参考我用cmets设置的Git repo。它还包括playwright 的示例代码。
【讨论】:
我已经尝试了很多解决方案,但在我的情况下只有这个工作,除了await page.goto
抛出 net::ERR_ABORTED 错误。通过捕获错误并忽略它,然后验证本地路径中的文件以确认下载成功或不解决问题。【参考方案2】:
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 月)。
【讨论】:
以上是关于使用特定配置打开 Puppeteer(下载 PDF 而不是 PDF 查看器)的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 puppeteer 和 Node js 为 pdf 页面生成屏幕截图