You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何开发Chrome扩展下载Struts框架流式传输的PDF文件?

解决方案:Chrome扩展一键下载流式PDF

核心逻辑

页面里的embed元素源是Data URI(格式为data:application/pdf;base64,...的长字符串),本质是Base64编码的PDF内容。我们只需要提取该编码内容,解码后生成PDF文件并触发浏览器下载即可。

扩展实现步骤

1. 搭建扩展基础结构

创建以下核心文件:

  • manifest.json:扩展配置文件
  • content.js:注入目标页面的脚本,负责提取PDF编码内容
  • popup.html:扩展弹窗,提供一键下载入口

manifest.json 配置示例

{
  "manifest_version": 3,
  "name": "流式PDF下载器",
  "version": "1.0",
  "permissions": ["activeTab", "downloads"],
  "content_scripts": [
    {
      "matches": ["*://你的系统域名/*.action"],
      "js": ["content.js"]
    }
  ],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icon16.png",
      "48": "icon48.png"
    }
  }
}

注意:替换你的系统域名为实际系统域名,图标文件可自行准备或省略

2. 编写内容脚本(content.js)

负责定位embed元素并提取Base64编码的PDF内容:

// 提取PDF的Base64编码内容
function getPdfBase64() {
  const embed = document.querySelector('embed');
  if (!embed || !embed.src.startsWith('data:application/pdf;base64,')) {
    return null;
  }
  return embed.src.split('base64,')[1];
}

// 监听来自弹窗的下载请求
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === 'downloadPdf') {
    const pdfBase64 = getPdfBase64();
    if (pdfBase64) {
      sendResponse({success: true, base64: pdfBase64});
    } else {
      sendResponse({success: false, message: '未找到可下载的PDF内容'});
    }
  }
});

3. 实现弹窗页面(popup.html)

提供可视化的下载按钮,并处理下载逻辑:

<!DOCTYPE html>
<html>
<head>
  <style>
    body {width: 150px; padding: 10px; margin: 0;}
    button {width: 100%; padding: 8px; cursor: pointer; border: none; border-radius: 4px; background: #0078d4; color: #fff;}
  </style>
</head>
<body>
  <button id="downloadBtn">下载PDF</button>
  <script>
    document.getElementById('downloadBtn').addEventListener('click', async () => {
      const [tab] = await chrome.tabs.query({active: true, currentWindow: true});
      const response = await chrome.tabs.sendMessage(tab.id, {action: 'downloadPdf'});
      
      if (response.success) {
        // 将Base64转为Blob对象
        const byteChars = atob(response.base64);
        const byteNumbers = new Array(byteChars.length);
        for (let i = 0; i < byteChars.length; i++) {
          byteNumbers[i] = byteChars.charCodeAt(i);
        }
        const byteArray = new Uint8Array(byteNumbers);
        const pdfBlob = new Blob([byteArray], {type: 'application/pdf'});
        
        // 生成临时URL并触发下载
        const tempUrl = URL.createObjectURL(pdfBlob);
        chrome.downloads.download({
          url: tempUrl,
          filename: '文档.pdf',
          saveAs: true
        }, () => {
          URL.revokeObjectURL(tempUrl); // 释放临时资源
        });
      } else {
        alert(response.message);
      }
    });
  </script>
</body>
</html>

替代方案:右键菜单触发下载

如果不需要弹窗,可添加右键菜单选项:

  1. manifest.json中更新权限和后台脚本配置:
"background": {
  "service_worker": "background.js"
},
"permissions": ["activeTab", "downloads", "contextMenus"]
  1. 创建background.js
chrome.runtime.onInstalled.addListener(() => {
  chrome.contextMenus.create({
    id: 'downloadPdf',
    title: '下载当前PDF',
    contexts: ['page']
  });
});

chrome.contextMenus.onClicked.addListener(async (info, tab) => {
  if (info.menuItemId === 'downloadPdf') {
    const response = await chrome.tabs.sendMessage(tab.id, {action: 'downloadPdf'});
    if (response.success) {
      const byteChars = atob(response.base64);
      const byteNumbers = new Array(byteChars.length);
      for (let i = 0; i < byteChars.length; i++) {
        byteNumbers[i] = byteChars.charCodeAt(i);
      }
      const byteArray = new Uint8Array(byteNumbers);
      const pdfBlob = new Blob([byteArray], {type: 'application/pdf'});
      const tempUrl = URL.createObjectURL(pdfBlob);
      chrome.downloads.download({
        url: tempUrl,
        filename: '文档.pdf',
        saveAs: true
      }, () => {
        URL.revokeObjectURL(tempUrl);
      });
    } else {
      alert('未找到可下载的PDF内容');
    }
  }
});

注意事项

  • 若embed的src是Blob URL而非Data URI,需调整提取逻辑,通过fetch获取Blob内容
  • 测试时需在Chrome扩展管理页面开启「开发者模式」,加载已解压的扩展文件夹
  • 可根据页面标题动态生成文件名,替换代码中的文档.pdf即可

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

火山引擎 最新活动