接口参考
API 总览
浏览器 SDK 的全部方法:连接与授权、打印机、打印、预览、扫描、任务。每个方法给出签名、参数、返回值与示例。
最后更新
本页是网页可用接口的完整清单。所有方法都是 Promise 风格,失败抛出结构化错误
(code / message / retryable),见错误码。
网页只做这些
桌面端内部的特权能力(设置写入、任务内容查看器、服务迁移事务等)不是网页 API, 网页永远无法调用。网页能用的就是本页列出的内容。
端点与创建
| 项 | 值 |
|---|---|
| 默认端点 | ws://127.0.0.1:17888/ws |
| 协议 | printlink.v1(报文里的 v 固定为 1) |
| 浏览器 SDK | http://127.0.0.1:17888/sdk/printlink.js(全局 PrintLink) |
| npm 包 | @printlink/sdk |
| 健康检查 | GET /healthz |
| HTTP 接口 | POST /rpc(同端口,见 HTTP 接口) |
| 扫描成品下载 | GET /api/v1/scans/{scanId}/pages/{index} |
import { PrintLinkClient } from '@printlink/sdk';
const client = new PrintLinkClient({
appName: '我的业务系统', // 显示在配对确认与站点列表
channel: 'erp', // 可选:区分同一台机器上的不同业务程序
endpoint: 'ws://127.0.0.1:17888/ws',// 可选,默认即此
requestTimeoutMs: 30_000, // 可选,单次请求超时
});连接与授权
detect() → connect() → ensureAuthorized() → 业务调用 … → close()| 方法 | 返回 | 说明 |
|---|---|---|
PrintLinkClient.detect(options?) | DetectResult | 静态方法,不需要实例:installed / reachable / version / reason |
connect() | HelloResult | 建立连接:agentVersion / protocolVersion / platform / features |
ensureAuthorized(permissions?) | AuthStatusResult | 已授权直接返回,否则发起配对。也接受 { requestedPermissions, waitForDecision, timeoutMs, signal } |
authStatus() | AuthStatusResult | 查询当前授权状态与已授予权限 |
pair(permissions?) | AuthPairResult | 显式发起配对(本机弹确认框) |
revoke() | void | 撤销本站点自己的令牌 |
onConnectionStateChange(listener) | 取消函数 | 订阅连接 / 授权 / 就绪状态快照 |
onAuthDecisionChanged(handler) | 取消函数 | 用户在电脑上批准或拒绝了配对 |
onServiceMigrated(handler) | 取消函数 | 服务端口变更通知 |
close() | void | 断开并清理订阅,离开页面务必调用 |
ensureAuthorized({ waitForDecision: true }) 会等用户做完决定,而不是立刻以
PAIRING_PENDING 失败——适合「点了打印再等授权」的交互。
features 是特性列表(如 scanner.v1),用它做特性检测而不是比较版本号。
打印机与配置档
| 方法 | 返回 | 说明 |
|---|---|---|
listPrinters() | { devices, queues } | 打印队列(含实时状态)与物理设备分组 |
defaultPrinter() | string | null | 系统默认打印机的 queueId |
getCapabilities(queueId, refresh?) | PrinterCapabilities | 纸张、双面、色彩、份数、纸盒、介质、分辨率 |
printerStatus(queueId) | PrinterStatusSnapshot | 即时状态快照 |
onPrinterStatusChanged(handler) | 取消函数 | 打印机状态变化事件 |
setPreferredPrinter(queueId | null) | PrinterListResult | 设置 / 清除本机首选打印机 |
openPrinterSettings(queueId) | { opened } | 打开系统打印机设置 |
listProfiles(queueId?) | 配置档摘要数组 | 查询配置档 |
getProfile(id) | 配置档摘要 | 单个配置档 |
createProfileFromNative(queueId, name) | 配置档摘要 | 用打印机当前原生配置新建 |
renameProfile(id, name) | 配置档摘要 | 改名 |
setDefaultProfile(id) | 配置档摘要 | 设为该打印机默认 |
setProfileStandard(id, options) | 配置档摘要 | 写入跨平台标准选项 |
deleteProfile(id) | void | 删除 |
细节见打印机与配置档。
上传与打印
| 方法 | 返回 | 说明 |
|---|---|---|
uploadAsset(bytes, mime) | AssetRef | 上传 PDF / 图片,分块 + SHA-256 校验 |
validate(params) | JobValidateResult | 提交前校验:requested → effective + warnings,无副作用 |
compose({ queueId }) | PrintJobBuilder | 链式构建器,见下 |
print(params) | JobPrintResult | 静默打印,提交即返回 jobId |
printAndWait(params, options?) | JobStatusEventData | 提交并等待终态;options.onStatus 收中间状态,timeoutMs 默认 120 秒 |
打印参数 JobPrintParams
interface JobPrintParams {
queueId: string;
source: PrintSource; // { items: SourceItem[] },1..=50 项
options?: PrintOptions; // 见「打印参数」一页
profileId?: string; // 省略 = 打印机默认配置档;'' = 明确不用配置档
profileMode?: 'default' | 'explicit' | 'none'; // 三态写法
title?: string; // 任务标题,显示在控制台任务列表
idempotencyKey?: string; // 1..128 位可见 ASCII,重复提交只执行一次
channel?: string; // 区分业务程序:^[a-z][a-z0-9_-]*$,最长 64
}PrintSource / SourceItem
type SourceItem =
| { type: 'image'; asset?: AssetRef; remote?: { url: string }; pageLayout?: PageLayout }
| { type: 'pdf'; asset: AssetRef; pageRange?: string }
| { type: 'html'; asset?: AssetRef; remote?: { url: string }; pageRange?: string }
| { type: 'document'; document: PrintDocument; data?: unknown };asset 与 remote 二选一(两个都给或都不给都报 INVALID_REQUEST)。
remote 只接受公网地址,见内容来源。
PrintJobBuilder(compose() 的返回值)
| 方法 | 说明 |
|---|---|
.paper('auto' | name | PageSize) / .pageSize(w, h, unit?) | 任务纸张,只设一次 |
.copies(n) .orientation(v) .duplex(v) .color(bool) .borderless(bool) .quality(v) .mediaType(v) .tray(v) .collate(bool) .reverseOrder(bool) | 对应 options.* |
.pageLayout('auto' | 'actual' | 'fill') | 全任务统一预设,不接受 custom |
.margins(v) .outputPageRange(v) .options(patch) | 页边距、输出页段、批量补丁 |
.profile(id) .compatibility(mode) | 引用配置档、兼容模式 |
.title(t) .idempotencyKey(k) | 任务标题与幂等键 |
.addPdf(src) → .pageRange(r) | 一份 PDF |
.addImage(src) → .imageLayout(layout) | 一张图,可单独设置布局 |
.addHtml(src) → .pageRange(r) | 一段网页 |
.addDocument(doc) → .data(d) | 一份模板文档 + 该份数据 |
.add(item) | 直接放一个线格式项(如 Hiprint 转换结果) |
.validate() .preview() .print() .printAndWait() .toParams() | 提交 |
类型层面会挡住写错的组合:.addImage(x).pageRange()、.addPdf(x).imageLayout()、
任务级 .pageLayout({ mode: 'custom' }) 都是编译错误。
预览
| 方法 | 返回 | 说明 |
|---|---|---|
preview(params) | PreviewOpenResult | 打开预览窗口,参数与 print() 相同 |
previewUpdate({ previewSessionId, ... }) | PreviewOpenResult | 更新预览内容 |
previewGetPage(sessionId, pageIndex) | PreviewGetPageResult | 栅格化一页(仅本机受信界面) |
previewPrint(sessionId) | JobPrintResult | 打印预览中的同一份内容 |
previewClose(sessionId) | void | 关闭预览会话 |
interface PreviewOpenResult {
previewSessionId: string;
pageCount: number;
artifactSha256: string;
warnings: PrintWarning[];
windowShown: boolean;
source: SourceSummary; // 每项落在哪些输出页
}
interface PreviewUpdateParams {
previewSessionId: string;
source?: PrintSource; // 整份替换
options?: PrintOptions; // 整份替换
pageLayout?: PreviewPageLayoutUpdate; // 定向修改
queueId?: string;
profileId?: string;
profileMode?: 'default' | 'explicit' | 'none';
}
type PreviewPageLayoutUpdate =
| { scope: 'all'; layout: PageLayoutPreset }
| { scope: 'image'; itemIndex: number; layout: PageLayout };细节见预览。
任务
| 方法 | 返回 | 说明 |
|---|---|---|
getJob(jobId) | PrintJob | 任务详情(仅本站点提交的) |
listJobs(limit?) | PrintJob[] | 任务列表 |
cancelJob(jobId) | PrintJob | 取消任务 |
onJobStatus(handler) | 取消函数 | 任务状态流转事件 |
onDuplicateSuppressed(handler) | 取消函数 | 幂等键抑制了重复提交 |
getDiagnostics() | 诊断摘要 | 脱敏的系统信息 |
扫描
scanner.read / scan.run 不在默认权限范围内。
| 方法 | 说明 |
|---|---|
scannerList(refresh?) | 列出扫描仪 |
scannerGet(scannerId) | 单台信息 |
scannerCapabilities(scannerId, refresh?) | 来源 × 分辨率 × 颜色 × 格式 × 尺寸 |
scannerStatus(scannerId) | 即时状态 |
scanValidate(scannerId, options, compatibility?) | 无副作用校验 |
scanStart(params) | 创建作业(可能先进入等待确认) |
scan(params, options?) | 发起并等待终态 |
scanStatus(scanId) / scanList(limit?) | 查询 |
scanCancel(scanId) | 取消 |
scanGetPage(scanId, index, maxWidthPx?, pdfPage?) | 单页小图 |
fetchScanPage(scanId, index, ticket?) | 取回成品 Blob |
onScanStatus(handler) / onScanPageReady(handler) / onScannerListChanged(handler) | 事件 |
细节见扫描。
数据模型
type PageLayoutPreset =
| { mode: 'auto' } // 自适应:等比缩放到可打印区并居中,不裁切
| { mode: 'actual' } // 实际大小:1:1 居中,超出裁切
| { mode: 'fill' }; // 铺满:等比放大盖满可打印区,超出裁切
type PageLayout =
| PageLayoutPreset
| {
mode: 'custom';
horizontal?: 'left' | 'center' | 'right';
vertical?: 'top' | 'center' | 'bottom';
size?: { widthMm?: number; heightMm?: number }; // 与 scalePercent 互斥
scalePercent?: number; // (0, 1000]
offset?: { xMm?: number; yMm?: number };
rotate?: 0 | 90 | 180 | 270;
flipHorizontal?: boolean;
flipVertical?: boolean;
};
interface AssetRef { id: string; sha256: string; mime: string; size: number }
interface PreviewGetPageResult {
pageIndex: number;
widthPx: number;
heightPx: number;
pngBase64: string;
origin: { itemIndex: number; kind: string; itemPageIndex: number };
pageLayout: PageLayout; // 该页实际布局,必填
layout?: PageLayoutGeometry; // 毫米几何
}能力解析是强制的
所有任务在渲染前都会经过能力解析:请求值(requested)按打印机真实能力解析为
有效值(effective),无法满足的部分降级并给出结构化 warnings。
validate() 让你在提交前拿到同一套结果。