如何使用Node.js打印PDF文件

This article was translated from English: Does it need improvement?
Translated
View the article in English

在Node.js中打印PDF文件需要将文档发送到操作系统的打印后台处理程序。 pdf-to-printer npm 包将该系统调用封装为基于 Promise 的 API,支持 Windows、macOS 和 Linux 系统,让您只需一次方法调用即可将打印任务加入队列。 在打印前生成PDF — 将HTML、URL或模板转换为可打印的文档 — IronPDF for Node.js自然而然地与此工作流配对。

快速入门:在Node.js中打印PDF文件

//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/quickstart.js
// 1. Install: npm install pdf-to-printer
const printer = require('pdf-to-printer');

// 2. Print the PDF file (returns a Promise)
printer
  .print('./invoice.pdf')
  .then(() => console.log('Print job queued successfully.'))
  .catch((err) => console.error('Print failed:', err));
//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/quickstart.js
// 1. Install: npm install pdf-to-printer
const printer = require('pdf-to-printer');

// 2. Print the PDF file (returns a Promise)
printer
  .print('./invoice.pdf')
  .then(() => console.log('Print job queued successfully.'))
  .catch((err) => console.error('Print failed:', err));
JAVASCRIPT

在Node.js中打印PDF的前置条件是什么?

使用 pdf-to-printer 之前,需安装 Node.js 14.x 或更高版本以及 npm。 该包依赖于本机操作系统打印命令而不是捆绑的打印引擎,因此目标机器上必须已经配置了打印机驱动程序。

Windows 上,该包通过PowerShell调用SumatraPDF。 确保PowerShell脚本执行未被系统策略阻止。 在 macOS 和 Linux 系统上,该软件包会调用 lp 命令,该命令是 CUPS 打印系统的一部分。 请确认已安装 CUPS,并且至少有一台打印机已注册到 lpstat -p

请注意推荐使用Node.js 18.x LTS用于生产工作负载。 pdf-to-printer 软件包支持所有当前有效的 Node.js LTS 版本。)]

如何设置Node.js项目以打印PDF?

在编写任何打印逻辑前,初始化新项目,安装该包,并创建一个最小的目录结构。

//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/setup.sh
mkdir pdf-printer
cd pdf-printer
npm init -y
npm install pdf-to-printer
//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/setup.sh
mkdir pdf-printer
cd pdf-printer
npm init -y
npm install pdf-to-printer
SHELL

安装完成后,请创建一个 index.js 文件来存放您的打印逻辑,并创建一个 pdfs/ 文件夹来存放您想要打印的文档。 通过单独的 config.js 代码块管理打印机设置,可将打印机名称与核心逻辑分离——这在开发环境与生产环境目标打印机不同的多环境部署场景中,是一种非常实用的模式。

该模块使用运行时解析的本机绑定,因此不需要编译步骤。 node_modules/pdf-to-printer/dist/ 目录将包含针对检测到的平台预编译的二进制文件。

如何使用基本用法打印PDF文件?

将绝对或相对文件路径传递给 printer.print()。 方法在系统默认打印机上将这份文档排队,并在作业被后处理程序接受时解决Promise — 而不是在物理打印完成时。

//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/basic-print.js
const fs = require('fs').promises;
const printer = require('pdf-to-printer');

async function printPDF(filePath) {
  // Verify the file exists before sending to printer
  await fs.access(filePath);

  const stats = await fs.stat(filePath);
  if (stats.size === 0) {
    throw new Error('PDF file is empty');
  }

  await printer.print(filePath);
  console.log(`Print job queued: ${filePath}`);
}

printPDF('./pdfs/invoice.pdf').catch((err) => {
  if (err.code === 'ENOENT') {
    console.error('File not found:', err.path);
  } else {
    console.error('Print error:', err.message);
  }
});
//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/basic-print.js
const fs = require('fs').promises;
const printer = require('pdf-to-printer');

async function printPDF(filePath) {
  // Verify the file exists before sending to printer
  await fs.access(filePath);

  const stats = await fs.stat(filePath);
  if (stats.size === 0) {
    throw new Error('PDF file is empty');
  }

  await printer.print(filePath);
  console.log(`Print job queued: ${filePath}`);
}

printPDF('./pdfs/invoice.pdf').catch((err) => {
  if (err.code === 'ENOENT') {
    console.error('File not found:', err.path);
  } else {
    console.error('Print error:', err.message);
  }
});
JAVASCRIPT

在调用 printer.print() 之前检查文件是否存在,可避免因路径错误或文件已被移动而导致的隐性失败。 如果路径无法解析,fs.access() 调用将抛出 ENOENT 异常,从而提供描述性错误信息,而非通用打印队列拒绝错误。 常见的错误原因包括不正确的相对路径、缺少打印机驱动程序和打印机离线状态。

重要当打印作业被操作系统后台处理程序接受时Promise才会解析,而不是在文档完成打印时。 为了审计目的,记录解析时的时间戳,而不是假设文档已离开打印机。)}]

如何在打印前生成PDF?

如果文档尚未以文件形式存在,请在调用 printer.print() 之前,使用 IronPDF for Node.js 生成该文件。 IronPDF将HTML、URL和模板字符串渲染成可打印的PDF文件,无需单独的浏览器实例。

//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/generate-and-print.js
const { PdfDocument } = require('@ironsoftware/ironpdf');
const printer = require('pdf-to-printer');

async function generateAndPrint(htmlContent, outputPath) {
  // Render HTML to a PDF file using IronPDF
  const pdf = await PdfDocument.fromHtml(htmlContent);
  await pdf.saveAs(outputPath);

  // Send the generated file to the default printer
  await printer.print(outputPath);
  console.log(`Generated and printed: ${outputPath}`);
}

generateAndPrint('<h1>Monthly Report</h1><p>Sales data for May 2026.</p>', './pdfs/report.pdf');
//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/generate-and-print.js
const { PdfDocument } = require('@ironsoftware/ironpdf');
const printer = require('pdf-to-printer');

async function generateAndPrint(htmlContent, outputPath) {
  // Render HTML to a PDF file using IronPDF
  const pdf = await PdfDocument.fromHtml(htmlContent);
  await pdf.saveAs(outputPath);

  // Send the generated file to the default printer
  await printer.print(outputPath);
  console.log(`Generated and printed: ${outputPath}`);
}

generateAndPrint('<h1>Monthly Report</h1><p>Sales data for May 2026.</p>', './pdfs/report.pdf');
JAVASCRIPT

这种模式在报告工作流中很常见,其中PDF内容在运行时从数据库记录或API响应中组装。 请参阅HTML到PDF转换教程,以完整了解IronPDF的渲染选项,包括CSS支持和页眉/页脚注入。

如何指定自定义打印机选项?

printer选项s 对象作为第二个参数传递给 printer.print(),以指定特定打印机、设置复印份数、选择页面范围或控制页面缩放比例。 打印机名称必须与 printer.getPrinters() 返回的精确值完全一致。

//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/custom-options.js
const printer = require('pdf-to-printer');

async function printWith选项s(filePath) {
  // List available printers to find the correct name
  const printers = await printer.getPrinters();
  printers.forEach((p) => {
    console.log(`${p.name} -- default: ${p.isDefault}`);
  });

  const options = {
    printer: 'HP LaserJet Pro',  // Exact name from getPrinters()
    copies: 2,                   // Number of copies
    pages: '1-3,5',              // Pages to print (optional)
    scale: 'fit',                // 'fit' | 'noscale' | 'shrink'
    orientation: 'portrait',     // 'portrait' | 'landscape'
  };

  await printer.print(filePath, options);
  console.log(`Printed ${options.copies} copies to "${options.printer}"`);
}

printWith选项s('./pdfs/shipping-label.pdf').catch(console.error);
//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/custom-options.js
const printer = require('pdf-to-printer');

async function printWith选项s(filePath) {
  // List available printers to find the correct name
  const printers = await printer.getPrinters();
  printers.forEach((p) => {
    console.log(`${p.name} -- default: ${p.isDefault}`);
  });

  const options = {
    printer: 'HP LaserJet Pro',  // Exact name from getPrinters()
    copies: 2,                   // Number of copies
    pages: '1-3,5',              // Pages to print (optional)
    scale: 'fit',                // 'fit' | 'noscale' | 'shrink'
    orientation: 'portrait',     // 'portrait' | 'landscape'
  };

  await printer.print(filePath, options);
  console.log(`Printed ${options.copies} copies to "${options.printer}"`);
}

printWith选项s('./pdfs/shipping-label.pdf').catch(console.error);
JAVASCRIPT

在调用 getPrinters() 之前先调用 print() 有两个目的:一是确认打印机处于联机状态且可访问,二是获取操作系统用于路由打印作业的权威名称字符串。 打印机名称往往包含与系统设置中显示名不同的版本号或网络后缀。

提示在 Windows 系统中,getPrinters() 会从注册表中返回打印机列表。 在macOS/Linux上,它查询CUPS。 isDefault 标志用于标识在未指定打印机名称时接收打印任务的打印机。

可以配置哪些打印机选项?

printer选项s 对象支持以下字段:

pdf-to-printer option properties
选项翻译类型说明示例值
打印机字符串正如getPrinters()返回的确切打印机名'HP LaserJet Pro'
副本数字打印份数2
页面字符串页范围字符串'1-3,5'
scale字符串页面缩放模式'fit''noscale''shrink'
方向字符串页面方向覆盖'portrait''landscape'

对于需要自定义纸张尺寸或需要在PDF生成过程中应用特定页面方向的文档,在保存文件之前在IronPDF渲染步骤中配置这些选项。

如何在Node.js中实现批量打印?

通过遍历数组并针对每个文件调用 printer.print(),处理一个 PDF 文件夹或动态生成的列表。将 for...ofawait 结合使用可确保任务顺序执行,从而防止打印后台处理程序因同时处理大量请求而过载。

//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/batch-print.js
const printer = require('pdf-to-printer');
const fs = require('fs').promises;
const path = require('path');

class BatchPrinter {
  constructor(printerName = null) {
    this.printerName = printerName;
    this.queue = [];
  }

  async addFiles(filePaths) {
    for (const filePath of filePaths) {
      try {
        await fs.access(filePath);
        this.queue.push(filePath);
      } catch {
        console.warn(`Skipped (not found): ${filePath}`);
      }
    }
  }

  async printAll(options = {}) {
    const results = { successful: 0, failed: 0, errors: [] };

    for (const filePath of this.queue) {
      try {
        const print选项s = {
          ...options,
          ...(this.printerName && { printer: this.printerName }),
        };
        await printer.print(filePath, print选项s);
        results.successful++;
        console.log(`Printed: ${path.basename(filePath)}`);
      } catch (err) {
        results.failed++;
        results.errors.push({ file: filePath, error: err.message });
      }
    }

    this.queue = [];
    return results;
  }
}

// Usage: print monthly reports to a specific printer
(async () => {
  const batch = new BatchPrinter('Office Printer A3');

  await batch.addFiles([
    './reports/january.pdf',
    './reports/february.pdf',
    './reports/march.pdf',
  ]);

  const results = await batch.printAll({ copies: 1 });
  console.log(`Done -- ${results.successful} printed, ${results.failed} failed.`);
})();
//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/batch-print.js
const printer = require('pdf-to-printer');
const fs = require('fs').promises;
const path = require('path');

class BatchPrinter {
  constructor(printerName = null) {
    this.printerName = printerName;
    this.queue = [];
  }

  async addFiles(filePaths) {
    for (const filePath of filePaths) {
      try {
        await fs.access(filePath);
        this.queue.push(filePath);
      } catch {
        console.warn(`Skipped (not found): ${filePath}`);
      }
    }
  }

  async printAll(options = {}) {
    const results = { successful: 0, failed: 0, errors: [] };

    for (const filePath of this.queue) {
      try {
        const print选项s = {
          ...options,
          ...(this.printerName && { printer: this.printerName }),
        };
        await printer.print(filePath, print选项s);
        results.successful++;
        console.log(`Printed: ${path.basename(filePath)}`);
      } catch (err) {
        results.failed++;
        results.errors.push({ file: filePath, error: err.message });
      }
    }

    this.queue = [];
    return results;
  }
}

// Usage: print monthly reports to a specific printer
(async () => {
  const batch = new BatchPrinter('Office Printer A3');

  await batch.addFiles([
    './reports/january.pdf',
    './reports/february.pdf',
    './reports/march.pdf',
  ]);

  const results = await batch.printAll({ copies: 1 });
  console.log(`Done -- ${results.successful} printed, ${results.failed} failed.`);
})();
JAVASCRIPT

BatchPrinter 类将验证与执行分离。 在 addFiles() 过程中,不存在的文件将被跳过,以避免因单个缺失文件导致整个批处理任务中止。 printAll() 方法会记录每个文件的错误,并返回一份摘要,该摘要可用于日志记录或转发至监控服务。

对于动态生成的报告,将此模式与IronPDF的HTML字符串到PDF转换结合使用以在单个管道中生成和打印。PDF压缩示例值得在大批量打印之前应用,以减少网络打印机上的后台传输时间。

提示如果打印机支持打印队列,请在任务之间添加短暂的 await 延迟——某些较旧的网络打印机不接受快速连续的提交。 200-500毫秒的暂停通常是足够的。

Node.js PDF打印的特定平台注意事项是什么?

pdf-to-printer 包在不同操作系统上使用不同的系统命令。 [@2:(理解底层机制有助于诊断特定平台的故障。)]

[@3:(### PDF打印在Windows上如何工作?)]

在 Windows 系统中,pdf-to-printer 会通过 PowerShell 命令调用 SumatraPDF。 [@5:(SumatraPDF已与包捆绑,无需单独安装。)] [@6:(必须在当前执行策略下允许PowerShell脚本执行。)] 在 PowerShell 中运行 Get-ExecutionPolicy 进行验证; 如果结果为 Restricted,请将其设置为 RemoteSignedBypass 以完成本次会话。

[@9:(Windows上的打印机名称区分大小写,必须与设置 > 蓝牙和设备 > 打印机和扫描仪中显示的值完全匹配,包括任何括号中的网络后缀。)]

[@10:(### PDF打印在macOS和Linux上如何工作?)]

在 macOS 和 Linux 系统上,该软件包调用 lp(属于 CUPS 组件)。 使用 lpstat -p 确认 CUPS 是否正在运行——这将列出所有已注册的打印机及其当前状态。 [@13:(如果没有打印机出现,可能是CUPS服务未启动;)] 在 Linux 系统中使用 sudo systemctl start cups,或在 macOS 系统中通过"系统偏好设置">"打印机"启用该功能。

lp 命令不支持 Windows SumatraPDF 路径中的所有相同选项。 根据打印机驱动程序的不同,scaleorientation 选项可能对基于 CUPS 的打印没有影响。 [@17:(在部署之前在目标硬件上测试。)]

警告pdf-to-printer 包目前仅支持打印到本地和网络打印机。 [@19:(通过该包不支持像Microsoft Universal Print这样的云打印服务。)])]

[@20:(## 如何处理打印PDF时的安全性和权限?)]

[@21:(处理敏感文件(合同、财务记录、医疗表格)的生产打印系统需要访问控制和审计跟踪。)] [@22:(跟踪谁打印了什么及何时打印是许多受监管行业的合规要求。)]

//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/secure-print.js
const printer = require('pdf-to-printer');
const crypto = require('crypto');

class AuditedPrinter {
  constructor() {
    this.log = [];
  }

  async print(filePath, userId, options = {}) {
    const jobId = crypto.randomBytes(8).toString('hex');
    const entry = { jobId, userId, filePath, options, status: 'pending', startedAt: new Date().toISOString() };
    this.log.push(entry);

    try {
      await printer.print(filePath, options);
      entry.status = 'completed';
      entry.completedAt = new Date().toISOString();
      return { success: true, jobId };
    } catch (err) {
      entry.status = 'failed';
      entry.error = err.message;
      throw err;
    }
  }

  getLog(userId = null) {
    return userId ? this.log.filter((e) => e.userId === userId) : this.log;
  }
}

// Usage
const auditedPrinter = new AuditedPrinter();

(async () => {
  await auditedPrinter.print('./contracts/nda-2026.pdf', 'user-42', { copies: 1 });
  console.log('Audit log:', auditedPrinter.getLog('user-42'));
})();
//:path=/static-assets/pdf/content-code-examples/nodejs/how-to/nodejs-print-pdf/secure-print.js
const printer = require('pdf-to-printer');
const crypto = require('crypto');

class AuditedPrinter {
  constructor() {
    this.log = [];
  }

  async print(filePath, userId, options = {}) {
    const jobId = crypto.randomBytes(8).toString('hex');
    const entry = { jobId, userId, filePath, options, status: 'pending', startedAt: new Date().toISOString() };
    this.log.push(entry);

    try {
      await printer.print(filePath, options);
      entry.status = 'completed';
      entry.completedAt = new Date().toISOString();
      return { success: true, jobId };
    } catch (err) {
      entry.status = 'failed';
      entry.error = err.message;
      throw err;
    }
  }

  getLog(userId = null) {
    return userId ? this.log.filter((e) => e.userId === userId) : this.log;
  }
}

// Usage
const auditedPrinter = new AuditedPrinter();

(async () => {
  await auditedPrinter.print('./contracts/nda-2026.pdf', 'user-42', { copies: 1 });
  console.log('Audit log:', auditedPrinter.getLog('user-42'));
})();
JAVASCRIPT

AuditedPrinter 类会为每个 PRINT 请求分配一个唯一的作业 ID,并记录用户身份、文件路径和时间戳。 将 this.log 写入数据库或仅追加日志文件,即可将其转化为持久的审计记录。 [@25:(对于包含个人可识别信息的文件,考虑在它们到达打印队列之前使用IronPDF的PDF加密功能来保护静态文件。)]

[@26:(对于通过HTTP接受打印请求的服务器应用程序,在打印前验证文件类型和大小——拒绝任何不是有效PDF二进制的上传。)] 切勿在未经安全处理的情况下,将用户提供的文件路径直接传递给 printer.print()

[@28:([@n:(将审计日志存储在应用程序可写目录之外。)] [@29:(使用文件系统写入访问权限的攻击者不应能够篡改打印记录。)]]

[@30:(## Node.js PDF打印的下一步是什么?)]

本指南介绍了如何使用 pdf-to-printer 将现有 PDF 文件打印到本地和网络打印机,内容涵盖从基本的单文件打印到批处理队列、自定义打印机选项、平台注意事项,以及受监管环境中的审计日志记录。

[@32:(要通过PDF生成扩展此工作流程,开始IronPDF for Node.js的免费试用并按照HTML到PDF教程构建端到端文档管道。有关许可选项和批量定价,请参阅IronPDF许可页面。)]

[@33:(准备好更进一步了吗?)] [@34:(探索完整的IronPDF for Node.js指南集合,学习如何合并PDF文件压缩PDF文件转换PDF为图像。)]

常见问题解答

在 Node.js 中打印 PDF 文件的最简单方法是什么?

使用pdf-to-printer npm包。通过npm install pdf-to-printer安装,然后调用printer.print('./file.pdf') -- 它返回一个Promise并在单次调用中使用系统默认打印机排队作业。

在 Node.js 中打印 PDF 的前提条件是什么?

Node.js 14.x或更高版本、npm和配置好的打印机驱动程序。在Windows上,PowerShell执行策略必须允许脚本执行。在macOS和Linux上,必须安装并运行CUPS,并通过lpstat -p注册至少一个打印机。

如何在Node.js中打印至特定打印机?

printerOptions对象作为printer.print()的第二个参数传入。将printer字段设置为printer.getPrinters()返回的确切打印机名称。打印机名称区分大小写,必须与操作系统注册表条目完全匹配。

我可以在同一个Node.js脚本中生成PDF然后打印吗?

可以。使用IronPDF for Node.js先生成文件:调用PdfDocument.fromHtml(html)渲染HTML内容,用pdf.saveAs(path)保存,然后将该路径传给printer.print(path)。通过npm install @ironsoftware/ironpdf安装IronPDF。

pdf-to-printer能在macOS和Linux上工作吗?

可以。在macOS和Linux上,包委托给CUPS的lp命令。用lpstat -p确认CUPS正在运行。注意,scaleorientation选项可能无法在所有CUPS打印机驱动程序上生效。

如何在Node.js中为打印作业添加日志?

printer.print()包装在一个类中,使用crypto.randomBytes(8).toString('hex')分配唯一作业ID,并记录文件路径、用户ID和时间戳。将日志数组持久化到应用程序可写目录之外的数据库或仅追加文件中。

Darrius Serrant
全栈软件工程师(WebOps)

Darrius Serrant 拥有迈阿密大学的计算机科学学士学位,目前在 Iron Software 担任全栈 WebOps 市场工程师。从小就被编码吸引,他认为计算机既神秘又易于接触,使其成为创意和问题解决的理想媒介。

在 Iron Software,Darrius 喜欢创造新事物,并简化复杂概念以使其更易理解。作为我们常驻的开发者之一,他还自愿教授学生,与下一代分享他的专业知识。

对于 Darrius 来说,他的工作令人满意,因为它被重视并产生真正的影响。

准备开始了吗?
版本: 2026.5 just released
Still Scrolling Icon

还在滚动吗?

想快速获得证据?
运行示例看着你的HTML代码变成PDF文件。