核心功能

扫描

列出扫描仪、读能力、发起扫描、桌面确认与取回成品。

最后更新

扫描与打印是相互独立的能力:扫描失败、设备忙碌都不会影响打印。

权限与确认

扫描权限不在默认授予范围内,需要单独申请:scanner.read(看设备)与 scan.run(发起扫描)。scan.run 每次扫描都会在桌面端弹出确认, 用户同意后才扫。无头服务默认直接拒绝。

完整流程

await client.ensureAuthorized(['scanner.read', 'scan.run']);

const { scanners } = await client.scannerList();
const scanner = scanners[0];
if (!scanner) throw new Error('没有可用扫描仪');

// 可选:先确认参数在设备上会被如何处理
const check = await client.scanValidate(scanner.scannerId, {
  source: 'platen',          // platen 平板 / feeder 进纸器
  format: 'image/jpeg',
});

// 发起扫描并等待终态(含用户确认的时间)
const job = await client.scan({
  scannerId: scanner.scannerId,
  options: { source: 'platen', format: 'image/jpeg' },
  title: '身份证正面',
});

for (const page of job.pages) {
  const blob = await client.fetchScanPage(job.scanId, page.index, page.downloadTicket);
  // 用这个 Blob:URL.createObjectURL(blob) 预览,或上传到你的后端
}

scan() 会一直等到用户在桌面端确认、拒绝或超时(默认 120 秒)。用户拒绝得到 SCAN_CONSENT_DENIED,超时得到 SCAN_CONSENT_TIMEOUT。

读设备能力与状态

const caps = await client.scannerCapabilities(scannerId);
// 进纸来源 × 分辨率 × 颜色模式 × 输出格式 × 尺寸

const status = await client.scannerStatus(scannerId);

和打印一样,只提供能力清单里有的选项。参数会经过与打印相同的能力校验, 不支持的取值会降级并给警告;用 scanValidate 可以在真正扫描前拿到结果。

取回成品

成品字节不走 WebSocket,而是同端口的 HTTP 下载:

const blob = await client.fetchScanPage(scanId, pageIndex, page.downloadTicket);
  • downloadTicket 是页元数据里带的短时票据,只发给发起扫描的那个站点; 不传则自动使用当前授权令牌。
  • 其他来源拿不到这些文件,只会得到 SCAN_NOT_FOUND,不泄露作业是否存在。
  • 成品只在本机临时保留(默认 10 分钟、总量默认 512 MiB),重启即清空。 过期或被清理后返回 CONTENT_EXPIRED,所以要及时下载。

控制台「设置 → 缓存 → 扫描件缓存」可以查看、另存为、删除或清空已完成的扫描件。

取消与查询

await client.scanCancel(scanId);         // 取消进行中的扫描
const list = await client.scanList(20);  // 本站点的扫描记录
const job = await client.scanStatus(scanId);

常见错误

错误码含义
PERMISSION_DENIED没申请 scanner.read / scan.run
SCAN_DISABLED设置里关闭了扫描
SCAN_CONSENT_DENIED / SCAN_CONSENT_TIMEOUT用户拒绝,或确认超时
SCANNER_BUSY设备被占用,稍后重试
UNSUPPORTED_SCAN_OPTION参数超出设备能力
SCAN_SOURCE_EMPTY进纸器没纸
SCAN_TOO_LARGE / SCAN_TIMEOUT页数、体积或时长超限
CONTENT_EXPIRED成品已过期或被清理

相关页面

本页目录