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

如何下载JavaScript生成的Blob格式PDF?Chrome PDF Viewer访问问题

解决Playwright下载Blob格式PDF的问题

先修正你原有代码的错误

你之前的代码里,Promise.all中传入了await page.click("xpath=//button[@ng-click='yes()']"),这会导致点击操作在waitForEvent开始监听之前就执行了,自然捕获不到下载事件。正确的写法写法是直接传递page.click()返回的Promise:

async function playwrightDownload(page){
  const [download] = await Promise.all([
    page.waitForEvent('download'),
    page.getByRole('button', {name: 'Download PDF'}).click(),
    page.click("xpath=//button[@ng-click='yes()']")
  ]);
  
  await download.saveAs("test.pdf");
}

但这个写法可能还是无法触发download事件,因为Chrome会默认预览PDF而不是直接下载,下面是几个更可靠的方案:

方案1:拦截网络响应直接获取PDF内容

既然PDF是以Blob形式加载的,我们可以拦截页面的网络响应,直接提取PDF的二进制内容保存:

const fs = require('fs');

async function downloadBlobPDF(page) {
  let pdfBuffer = null;

  // 监听所有响应,筛选出PDF类型的Blob请求
  const responseListener = async (response) => {
    const contentType = response.headers()['content-type'];
    if (response.url().startsWith('blob:') && contentType === 'application/pdf') {
      pdfBuffer = await response.body();
    }
  };
  page.on('response', responseListener);

  // 触发完整的下载流程
  await page.getByRole('button', {name: 'Download PDF'}).click();
  await page.click("xpath=//button[@ng-click='yes()']");

  // 等待PDF内容获取完成
  while (!pdfBuffer) {
    await page.waitForTimeout(100);
  }

  // 保存文件
  fs.writeFileSync('test.pdf', pdfBuffer);

  // 移除监听避免内存泄漏
  page.off('response', responseListener);
}

方案2:禁用Chrome PDF预览,强制直接下载

通过修改Chrome的启动参数,禁止PDF预览功能,这样点击下载时浏览器会直接触发download事件而不是打开预览窗口:

const { chromium } = require('playwright');

async function initBrowser() {
  const browser = await chromium.launch({
    args: [
      '--disable-pdf-viewer', // 禁用内置PDF查看器
      '--plugins=0', // 关闭插件支持
      '--download-restrictions=0' // 取消下载限制
    ]
  });
  const page = await browser.newPage();
  return { browser, page };
}

// 之后使用修正后的下载函数
async function playwrightDownload(page){
  const [download] = await Promise.all([
    page.waitForEvent('download'),
    page.getByRole('button', {name: 'Download PDF'}).click(),
    page.click("xpath=//button[@ng-click='yes()']")
  ]);
  
  await download.saveAs("test.pdf");
}

方案3:直接在页面内获取Blob内容并导出

如果PDF是前端JavaScript直接生成的(而非从后端接口获取),可以通过page.evaluate()在页面上下文里获取Blob的Base64编码,再传递到Node环境保存:

const fs = require('fs');

async function getGeneratedPDF(page) {
  // 触发下载流程,同时在页面内获取Blob内容
  const pdfBase64 = await page.evaluate(async () => {
    // 这里需要根据页面实际逻辑调整,比如找到生成PDF的函数
    // 假设页面中有一个返回Blob的generatePDF函数
    const pdfBlob = await window.generatePDF();
    
    // 将Blob转为Base64
    return new Promise((resolve) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result.split(',')[1]);
      reader.readAsDataURL(pdfBlob);
    });
  });

  // 将Base64转为Buffer并保存
  const pdfBuffer = Buffer.from(pdfBase64, 'base64');
  fs.writeFileSync('test.pdf', pdfBuffer);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 15:05:32