大数跨境

Bird 打印 PDF 的秘诀

Bird 打印 PDF 的秘诀 索引目录
2025-03-24
0
导读:在现代网络应用中,无需打开新的浏览器选项卡即可直接打印 PDF,从而提供更流畅的用户体验。

在现代网络应用中,无需打开新的浏览器选项卡即可直接打印 PDF,从而提供更流畅的用户体验。这种技术有时称为“静默打印”,在用户经常需要打印报告、发票或其他文档的商业应用中尤其有用。

今天,我将分享一个干净、可重复使用的 JavaScript 函数,它可以优雅地处理 PDF 打印,而不会中断用户的工作流程。

挑战

传统上,Web 应用程序中的 PDF 打印遵循以下流程:

  • 生成 PDF

  • 在新标签页中打开

  • 触发浏览器的打印对话框

  • 要求用户手动关闭标签页

这种方法会产生不必要的摩擦。它会打断用户的工作流程,让浏览器中的标签变得杂乱,并且需要额外点击才能返回应用程序。

更好的解决方案
下面的函数展示了鸟打印 PDF 的方式。

/**
* Prints a PDF silently using a hidden iframe
* @param {Function} generatePDF - Function that returns a PDF object
* @param {Object} data - Data required to generate the PDF
* @param {string} filename - Name for the PDF file (without extension)
* @param {Function} onSuccess - Optional callback on successful print
* @param {Function} onError - Optional callback on error
* @returns {Promise<void>} - Returns a promise that resolves when printing is complete
*/
const printPDFSilently = async (generatePDF, data, filename, onSuccess = () => { }, onError = () => { }) => {
try {
const pdf = await generatePDF(data);
const pdfUrl = URL.createObjectURL(pdf.output("blob"));

const iframe = document.createElement("iframe");
iframe.src = pdfUrl;
iframe.style.display = "none";
iframe.name = `${filename.replace(/\s+/g, "_")}.pdf`;
document.body.appendChild(iframe);

const print = async () => {
await new Promise((resolve) => {
iframe.contentWindow?.addEventListener("afterprint", () => {
URL.revokeObjectURL(pdfUrl);
document.body.removeChild(iframe);
resolve();
});
iframe.contentWindow?.print();
});
onSuccess();
};

iframe.contentWindow?.document.readyState === "complete" ? await print() : iframe.onload = print;
} catch (error) {
console.error("PDF printing error:", error);
onError(error);
}
};

它是如何工作的
让我们分解一下这个函数是如何工作的:

  1. PDF 生成:该函数接受generatePDF应返回 PDF 对象的回调(与 jsPDF 等库兼容)。

  2. Blob 创建:将 PDF 转换为 Blob 对象,并使用 创建临时 URL URL.createObjectURL()

  3. 隐藏的 iframe:该函数以 PDF URL 作为其源创建一个不可见的 iframe。

  4. 打印触发:当iframe加载时,该函数调用iframe.contentWindow.print()打开系统打印对话框。

  5. 清理:打印完成后,该函数撤销临时 URL 并从 DOM 中删除 iframe

  6. 错误处理:全面的错误处理确保发现并报告任何问题。

使用示例
下面介绍如何在 React 组件中使用此函数:

import { useState } from 'react';
import { jsPDF } from 'jspdf';
import { toast } from 'sonner';

const ReportPage = ({ userData }) => {
const [isPrinting, setIsPrinting] = useState(false);

const generateUserReport = (data) => {
const doc = new jsPDF();
doc.text(`User Report: ${data.fullName}`, 20, 20);
return doc;
};

const handlePrintReport = async () => {
setIsPrinting(true);
try {
await printPDFSilently(
generateUserReport,
userData,
`${userData.fullName}_Report`
);
toast.success("Printing initiated successfully!");
} catch (error) {
toast.error("Failed to prepare for printing. Please try again later.");
} finally {
setIsPrinting(false);
}
};

return (
<div>
<h1>User Report</h1>
<button
onClick={handlePrintReport}
disabled={isPrinting}
>
{isPrinting ? "Preparing…" : "Print Report"}
</button>
</div>
)
};

优点
这种方法有几个优点:

  • 改进的用户体验:无需切换标签或手动关闭

  • 更清晰的代码:可重用的功能,具有明确的关注点分离

  • 内存效率:适当清理资源

  • 灵活:可与任何 PDF 生成库配合使用

  • 可定制:与通知系统集成的成功和错误回调

浏览器兼容性
此技术适用于所有现代浏览器。但是,请注意:

  • 某些浏览器可能具有阻止自动打印的安全设置

  • 移动浏览器对 Print API 的支持程度各不相同

  • afterprint事件并未得到普遍支持(尽管我们的实现已经适当降级)

结论
静默 PDF 打印可在 Web 应用程序中创造更无缝的用户体验。通过使用上述技术,您可以为用户提供更流畅的工作流程,而无需担心打开和关闭新标签页带来的不愉快体验。

我们创建的可重用函数可处理所有复杂性,同时为您的应用程序代码提供干净的 API。这是一个小小的改进,但可以显著提高您的 Web 应用程序的感知质量。

请记住,该generatePDF功能是刻意分开的,允许您使用最适合您需求的 PDF 生成库(jsPDF、PDFMake 等),同时保持一致的打印体验。


【声明】内容源于网络
0
0
索引目录
索引目录是一家专注于医疗、技术开发、物联网应用等领域的创新型公司。我们致力于为客户提供高质量的服务和解决方案,推动技术与行业发展。
内容 444
粉丝 0
索引目录 索引目录是一家专注于医疗、技术开发、物联网应用等领域的创新型公司。我们致力于为客户提供高质量的服务和解决方案,推动技术与行业发展。
总阅读12
粉丝0
内容444