开始使用

快速上手

五步打出第一张纸:引入 SDK、连接授权、选打印机、打印、需要确认时先预览。附完整可复制示例。

最后更新

前提:目标电脑已安装并启动 PrintLink,控制台「总览」页能看到 ws://127.0.0.1:17888/ws,且你的网页和打印机在同一台电脑上(这是默认情况)。

1. 引入 SDK

PrintLink 自己就分发浏览器版 SDK,页面里加一行即可(全局变量 PrintLink):

<script src="http://127.0.0.1:17888/sdk/printlink.js"></script>

若改过端口,把 17888 换成实际端口。控制台「总览」页可一键复制这两个地址。

2. 连接并授权

const client = new PrintLink.PrintLinkClient({ appName: '我的业务系统' });

const hello = await client.connect();   // 连接本机 PrintLink
console.log(hello.agentVersion, hello.platform);

await client.ensureAuthorized();        // 已授权直接返回;否则发起配对

首次连接时,PrintLink 会在用户的电脑上弹出确认框:是否允许这个网站打印。 用户同意后,令牌保存在浏览器本地,之后不再打扰。

默认授予四项权限:查看打印机、查看配置、打印、预览。需要更多时在 ensureAuthorized(['job.read', 'job.cancel']) 里一并申请。

3. 选择打印机

const { queues } = await client.listPrinters();
const queueId =
  queues.find((q) => q.isUserPreferred)?.queueId ??   // 用户在控制台设为「首选」的
  queues.find((q) => q.isSystemDefault)?.queueId ??   // 系统默认打印机
  queues[0]?.queueId;

每个队列都带实时状态(status.state:ready / printing / paused / offline…)。需要知道支持哪些纸张、能不能双面时调用 client.getCapabilities(queueId),详见打印机与配置档。

4. 打印

compose() 是链式写法:按页序加内容、纸张设一次、最后一次提交(上传只做一次):

const bytes = new Uint8Array(await (await fetch('/invoice.pdf')).arrayBuffer());

const job = await client
  .compose({ queueId })
  .paper('A4')
  .title('发票 INV-2026-0001')
  .addPdf(bytes)
  .printAndWait();

console.log(job.status);   // 'completed' | 'failed' | 'canceled'
console.log(job.warnings); // 参数被降级时的说明,例如不支持双面而回退单面

5. 需要用户确认就先预览

preview() 与 print() 接受完全相同的参数,区别只是先弹预览窗口: 用户在窗口里看过后点打印,送进打印机的就是刚才看到的那一份,不会重新渲染。

const asset = await client.uploadAsset(bytes, 'application/pdf');
const session = await client.preview({
  queueId,
  source: { items: [{ type: 'pdf', asset }] },
});
console.log(session.pageCount, session.warnings);
// 用户在预览窗口确认;页面代码也可以主动触发打印:
// await client.previewPrint(session.previewSessionId);

页面上要处理的三种状态

这三种状态含义完全不同,不要都当成「打印失败」:

const probe = await PrintLink.detect();
if (!probe.installed) {
  // ① 没装或没启动:引导用户安装/启动,而不是直接 connect() 报错
  showInstallGuide();
} else {
  try {
    await client.connect();
    await client.ensureAuthorized();
  } catch (err) {
    if (err instanceof PrintLink.PrintLinkError && err.code === 'PAIRING_PENDING') {
      // ② 等用户授权:还没在电脑上点同意,提示后重试 ensureAuthorized()
      showWaitingForApproval();
    } else {
      // ③ 真的失败:按 err.code 给出说明
      showError(err.code, err.retryable);
    }
  }
}

所有失败都是结构化错误:code(稳定的机器码)+ message + retryable。 请始终按 code 分支,不要解析 message 文本。完整列表见错误码。

完整示例

可以整段复制到空白 HTML 页面运行(选择 PDF → 静默打印):

<!doctype html>
<meta charset="utf-8" />
<input id="file" type="file" accept="application/pdf" />
<button id="print" disabled>打印</button>
<pre id="log"></pre>

<script src="http://127.0.0.1:17888/sdk/printlink.js"></script>
<script type="module">
  const log = (msg) => (document.querySelector('#log').textContent += msg + '\n');
  const client = new PrintLink.PrintLinkClient({ appName: 'PrintLink 快速上手' });

  const probe = await PrintLink.detect();
  if (!probe.installed) {
    log('未检测到 PrintLink,请先安装并启动。');
  } else {
    await client.connect();
    await client.ensureAuthorized();
    log(`已连接 PrintLink v${probe.version}`);
    document.querySelector('#print').disabled = false;
  }

  client.onJobStatus((event) => log(`任务 ${event.jobId}: ${event.status}`));

  document.querySelector('#print').onclick = async () => {
    const file = document.querySelector('#file').files[0];
    if (!file) return log('请先选择 PDF');
    const { queues } = await client.listPrinters();
    const queueId = (queues.find((q) => q.isSystemDefault) ?? queues[0]).queueId;
    const job = await client.compose({ queueId }).title(file.name).addPdf(file).printAndWait();
    log(`终态:${job.status}`);
  };

  window.addEventListener('pagehide', () => client.close());
</script>

离开页面时记得 close()

client.close() 会断开连接并清理订阅。React / Vue 组件销毁时同样要调用, 否则开发时的热更新会不断累积连接。

下一步

本页目录