我在使用plasmo写一个谷歌插件。目标网站有一个按钮,点击就是打印数据,数据是通过接口获取的。需求是,通过插件批量自动点击打印,把打印预览的,重命名并另存为PDF。现在我发现,我获取不到打印预览弹窗的内容?
打印预览是浏览器的功能吧,不是网页功能,在 JS 控制的范围以外。所以你获取不到。
应该没什么解决方法,因为必须调用浏览器 API,没有就是没有。可以考虑换个技术方案,比如走 puppeteer。
在Plasmo框架中实现自动下载打印预览的PDF,需要绕过Chrome的安全限制。以下是完整方案:
// background.ts (后台服务)
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "savePDF") {
const { tabId, filename } = request;
// 附加调试器获取PDF数据
chrome.debugger.attach({ tabId }, "1.0", () => {
chrome.debugger.sendCommand(
{ tabId },
"Page.printToPDF",
{
transferMode: "ReturnAsBase64",
printBackground: true,
landscape: false,
displayHeaderFooter: false,
margin: { top: 0.4, bottom: 0.4, left: 0.4, right: 0.4 }
},
(pdfData) => {
if (chrome.runtime.lastError) {
console.error("PDF生成失败:", chrome.runtime.lastError);
return;
}
// 转换并下载PDF
const pdfBlob = base64ToBlob(pdfData.data, "application/pdf");
const url = URL.createObjectURL(pdfBlob);
chrome.downloads.download({
url: url,
filename: `${filename}.pdf`,
saveAs: true
}, () => URL.revokeObjectURL(url));
chrome.debugger.detach({ tabId });
}
);
});
}
return true;
});
function base64ToBlob(base64: string, mimeType: string) {
const byteCharacters = atob(base64);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += 1024) {
const slice = byteCharacters.slice(offset, offset + 1024);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
byteArrays.push(new Uint8Array(byteNumbers));
}
return new Blob(byteArrays, { type: mimeType });
}
// content.ts (内容脚本)
function automatePrinting() {
// 1. 找到打印按钮并触发点击
const printButton = document.querySelector('button.print-btn')!;
printButton.click();
// 2. 拦截打印请求
window.print = () => {
// 3. 发送生成PDF请求
chrome.runtime.sendMessage({
action: "savePDF",
filename: `report_${new Date().toISOString().slice(0, 10)}`,
tabId: chrome.devtools.inspectedWindow.tabId
});
};
}
// 当数据加载完成后执行
if (document.readyState === 'complete') {
automatePrinting();
} else {
window.addEventListener('load', automatePrinting);
}
manifest.json 权限声明:
{
"permissions": [
"debugger",
"downloads",
"scripting"
],
"host_permissions": ["<target_website>/*"]
}plasmo.manifest.json 额外配置:
{
"background": {
"service_worker": "background.ts",
"type": "module"
}
}拦截打印流程:
window.print()方法阻止默认弹窗PDF生成技术:
chrome.debuggerAPI获取原始PDF数据Page.printToPDF命令生成Base64编码的PDF文件下载:
chrome.downloadsAPI保存文件debugger权限,Chrome会显示警告条chrome.debugger的detach操作防止资源泄漏printBackground: true确保CSS样式完整输出如果不想使用debugger API,可考虑:
// 使用html2canvas+jsPDF(有样式失真风险)
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';
const printElement = document.getElementById('print-area');
html2canvas(printElement).then(canvas => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF('p', 'mm', 'a4');
pdf.addImage(imgData, 'PNG', 0, 0, 210, 297);
pdf.save('document.pdf');
});
推荐使用debugger方案,它能完美保留原始打印样式。注意在Chrome 111+版本中,可考虑新的
chrome.printingAPI(目前仅限ChromeOS)。实际部署时需处理网络延迟,建议在接口返回数据后添加500ms延时再触发打印。
不知道改到哪个地方了,只要点击刷新按钮,谷歌插件就自动打开了,或者是从新打开浏览器,插件也会自动跳出来。有哪位大神知道该怎么改吗
谷歌浏览器调用打印预览,如果去除另存为pdf选项? 希望目标打印机列表 只能选择打印机
最后,我们要给绘图程序增加打印和打印预览功能。我们希望文档分两页打印,第一页为封面,打印文档名字。第二页输出文档内容,并在页眉上打印文档名字。虽然AppWizard已经自动生成了打印和打印预览的代码,但是许多情况下,并不能符合要求。 这是因为: 1.打印机和窗口(屏幕)显示的分辨率不同:打印机的分辨率用每英寸多少个点来描述,屏幕分辨率用单位面积的像素点来表示。对于同样的Arial字体下的一个字
我在尝试从谷歌云存储下载CSV文件时遇到了一个问题。出于某种原因,它一直以字节而不是可读文本的形式下载文件。当我在Excel中打开下载的CSV时,Excel已经足够智能,可以将其转换为可读文本。我在这里错过了什么?我检查了谷歌的文档,但找不到任何好的信息来完成它们。提前谢谢你! 这是错误:UnicodeDecodeError:“utf-8”编解码器无法解码位置15-16的字节:无效的连续字节
我想知道是否有可能从谷歌云存储下载一个文件,它的名称与存储桶中的名称不同。 例如,在谷歌云存储中,我存储了一个名为的文件,但当我下载它时,我想选择一个不同的名称,比如说 我注意到下载的链接是这样的:https://storage.cloud.google.com/bucket_name/123-file.txt?response-内容处置=附件;filename=123-file.txt 因此,我
我已经在谷歌表单中创建了一个自定义表单。当用户按键盘上的[Enter]或[Tab]时,表单上数据字段的顺序与我想跳转到(下一个单元格)的顺序不同。是否有一个方法可以在工作表上使用(不使用谷歌应用程序脚本),我可以指定移动到下一个单元格。
我需要从我的谷歌云存储从我的桶中下载NodeJS文件夹。我读了所有的留档,我只找到了下载文件而不是文件夹的方法。我需要获取/下载文件夹以提供用户的下载文件。 有人能帮我吗?
我是一个非营利组织的谷歌办公套件管理员,刚刚发现了数据导出功能,这似乎就像个人账户的外卖。 导出文件已经准备好,现在可以从谷歌云平台存储中的存储桶下载。然而,有很多很多文件夹,试图进出每个文件夹来下载很多很多。每个文件中的zip文件听起来都是一个令人头疼的问题。 我在Mac上使用Transmit,它可以通过与Amazon S3的互操作性连接到谷歌云存储。然而,当我连接时,我什么也看不到(因为我不使