You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从浏览器PDF预览保存/下载PDF?Playwright遇内容损坏问题

问题:Playwright保存在线PDF文件内容损坏的解决方案

目标是下载在线PDF文件(示例地址:https://www.cheat-sheets.org/saved-copy/http-response-codes-1.pdf),使用以下Playwright代码执行后,本地保存的PDF内容损坏,但浏览器预览显示正常。尝试过切换媒体类型(print/screen)、截图、触发ctrl+s均无效。

现有代码

const playwright = require('playwright');

(async () => {
  const browser = await playwright.chromium.launch();
  const context = await browser.newContext();
  const page = await context.newPage();

  // await page.emulateMedia({ media: 'print' }); // Doesn't work also.
  await page.emulateMedia({ media: 'screen' });

  await page.goto('https://www.cheat-sheets.org/saved-copy/http-response-codes-1.pdf');

  console.log('Page Visited');

  await page.waitForTimeout(3000); // To wait for the pdf to be full loaded.

  console.log('Timeout Done');

  await page.pdf({ path: `document.pdf` });

  console.log('Document Saved');

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

问题现象

  • Playwright控制的浏览器预览PDF显示正常
  • 本地保存的document.pdf内容损坏,无法正常读取

解决方案

方案1:直接HTTP请求下载原PDF文件

page.pdf()是将网页渲染为PDF,而在线PDF是浏览器阅读器渲染的界面,并非普通HTML,因此该方法无法获取原文件。直接通过HTTP请求下载是最直接的方式:

const fetch = require('node-fetch');
const fs = require('fs').promises;

(async () => {
  const pdfUrl = 'https://www.cheat-sheets.org/saved-copy/http-response-codes-1.pdf';
  const response = await fetch(pdfUrl);
  
  if (!response.ok) {
    throw new Error(`请求失败:${response.status}`);
  }
  
  const pdfBuffer = await response.buffer();
  await fs.writeFile('document.pdf', pdfBuffer);
  
  console.log('原PDF文件已成功下载');
})();

方案2:通过浏览器上下文触发下载(适用于需要验证的场景)

如果目标PDF需要登录或其他验证才能访问,可以配置浏览器拦截请求,修改响应头触发下载:

const playwright = require('playwright');

(async () => {
  const browser = await playwright.chromium.launch();
  const context = await browser.newContext({
    acceptDownloads: true // 开启下载支持
  });
  const page = await context.newPage();

  // 拦截所有PDF请求,修改响应头触发下载
  await page.route('**/*.pdf', async (route) => {
    const originalResponse = await route.fetch();
    // 添加Content-Disposition头,让浏览器下载而非预览
    const modifiedHeaders = {
      ...originalResponse.headers(),
      'Content-Disposition': 'attachment; filename="document.pdf"'
    };
    
    await route.fulfill({
      response: originalResponse,
      headers: modifiedHeaders
    });
  });

  // 等待下载事件
  const downloadPromise = page.waitForEvent('download');
  await page.goto('https://www.cheat-sheets.org/saved-copy/http-response-codes-1.pdf');
  const download = await downloadPromise;

  // 保存下载的文件到本地
  await download.saveAs('document.pdf');
  
  console.log('PDF已通过浏览器下载保存');
  await browser.close();
})();

原因说明

page.pdf()方法的作用是将当前页面的HTML内容渲染生成PDF,而在线PDF是通过浏览器内置的PDF阅读器渲染展示的,本质上是阅读器的界面而非原PDF文件。因此用该方法保存的是阅读器的渲染结果,而非原文件,导致内容损坏。直接下载原文件或触发浏览器原生下载才能获取完整有效的PDF。

内容的提问来源于stack exchange,提问作者Jplus2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:02:32