快速上手
五步打出第一张纸:引入 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 组件销毁时同样要调用,
否则开发时的热更新会不断累积连接。