NexScanner Web SDK 封装了插件的 WebSocket 协议。业务系统只需要调用 SDK 方法,不需要自己处理原生 WebSocket、二进制图片帧、Base64 分块拼接和命令响应匹配。
文件位置
| 文件 | 说明 |
|---|---|
examples/sdk/nexscanner-sdk.js | 浏览器端 SDK |
examples/sdk/nexscanner-sdk.d.ts | TypeScript 类型声明 |
examples/sdk/nexscanner-sdk-demo.html | 完整 Demo |
docs/NexScanner-Web-SDK使用说明.html | 本说明文档 |
快速开始
先启动 NexScanner 插件,并确认 WebSocket 服务已启用。默认地址:
ws://127.0.0.1:11345/
在页面中引入 SDK:
<script src="./nexscanner-sdk.js"></script>
最小示例:
<img id="preview">
<script>
const scanner = new NexScannerClient({ url: 'ws://127.0.0.1:11345/' });
scanner.on('image', image => {
document.querySelector('#preview').src = image.url;
console.log('收到扫描图片', image.seq, image.blob);
});
async function startScan() {
await scanner.connect();
const devices = await scanner.listScanners();
await scanner.connectScanner(devices[0]);
await scanner.setParams({
resolution: 300,
colormode: 2,
duplex: 0,
source: 1,
format: 'jpg',
backend: 'WIA',
brightness: 0,
contrast: 0
});
await scanner.scan();
}
</script>
创建客户端
const scanner = new NexScannerClient({
url: 'ws://127.0.0.1:11345/',
timeout: 15000,
autoReconnect: false,
reconnectDelay: 3000
});
连接与设备
await scanner.connect();
const devices = await scanner.listScanners();
await scanner.connectScanner(devices[0]);
await scanner.disconnectScanner();
scanner.disconnect();
扫描参数
await scanner.setParams({
resolution: 300,
colormode: 2, // 0 黑白,1 灰度,2 彩色
duplex: 0, // 0 单面,1 双面
source: 1, // 0 自动,1 平板,2 ADF
pageSize: 0, // 纸张尺寸:0 A4(默认),1 A3,2 A5,3 A6,4 Letter,5 Legal,6 B5,7 自动
orientation: 0, // 纸张方向:0 纵向(默认),1 横向(平板横放),2 自动(平板按横竖并集)
format: 'jpg',
backend: 'WIA', // WIA / TWAIN / SCAN
brightness: 0, // 亮度,部分扫描仪不支持
contrast: 0 // 对比度,部分扫描仪不支持
});
const params = await scanner.getParams();
// params.pageSize → 当前纸张尺寸索引
// params.pageSizeName → 当前纸张尺寸名称,如 'A4'
// params.orientation → 当前纸张方向索引
// params.orientationName → 当前纸张方向名称,如 'Portrait' / 'Landscape'
const status = await scanner.getStatus();
纸张尺寸(pageSize)
插件在 Windows(WIA/TWAIN) 与 Linux/国产系统(SANE) 三端统一按 pageSize 下发幅面,默认 A4。
这样做的原因:部分 A3 幅面扫描仪在 Linux/国产系统下 SANE 的后端默认幅面是 A3,而 Windows 驱动默认是 A4,不显式指定时两端结果会不一致。
选 7(自动)则沿用设备/驱动默认幅面。
// 方式一:合并到 setParams
await scanner.setParams({ pageSize: 0 }); // A4
await scanner.setParams({ pageSize: 'A3' }); // 也支持枚举名(SDK 自动转换)
// 方式二:单独调用
await scanner.setPaperSize('A3');
await scanner.setPaperSize(NexScannerClient.PaperSize.A4);
// 常量表(window.NexScannerPaperSize 同名可用)
NexScannerClient.PaperSize.A4; // 0
NexScannerClient.PaperSize.A3; // 1
NexScannerClient.PaperSize.Auto; // 7
传了无法识别的值时 setParams / setPaperSize 会 reject(Invalid pageSize: xxx),不会再把这个参数发给插件。
纸张方向(orientation)
平板扫描时纸张可以竖放也可以横放:A4 竖放是 210×297,横放是 297×210。
只下发 pageSize 时扫描区域仍按 210×297 下发,横放的纸张会被裁掉,所以横放必须同时指定方向。
// 平板横放纸张
await scanner.setParams({ source: 1, pageSize: 0, orientation: 1 });
// 或者单独设置
await scanner.setPaperOrientation('landscape');
await scanner.setPaperOrientation(NexScannerClient.PaperOrientation.Landscape);
// 横竖都可能出现、不想每次切换 → 自动(平板按横竖并集 297×297 下发,ADF 仍按纵向)
await scanner.setPaperOrientation('auto');
NexScannerClient.PaperOrientation.Portrait; // 0 纵向(默认)
NexScannerClient.PaperOrientation.Landscape; // 1 横向
NexScannerClient.PaperOrientation.Auto; // 2 自动
三端实现:WIA 改 Page Width/Height、TWAIN 用 ICAP_UNITS+ICAP_FRAMES 下发扫描区域、SANE 改 --page-width/--page-height。
若某台设备/TWAIN 驱动不支持 ICAP_FRAMES,插件会在扫描日志里给出告警,此时平板横向扫描请改用 WIA 后端。
开始和停止扫描
await scanner.scan();
await scanner.stopScan();
扫描图片由插件主动推送,结果通过 image 事件返回,不是 scan() 的返回值。
scanner.on('image', image => {
console.log(image.seq);
console.log(image.format);
console.log(image.bytes); // ArrayBuffer
console.log(image.blob); // Blob
console.log(image.url); // 可直接给 img.src 使用
});
图片编辑
扫描图片编辑需要传入插件返回的图片序号 seq,会调用插件的 edit_image 接口。坐标和宽高均为相对比例,范围 0~1。
旋转
await scanner.rotateLeft(seq);
await scanner.rotateRight(seq);
await scanner.rotate180(seq);
await scanner.rotate(seq, 90);
裁剪
// 从图片 10%,10% 的位置开始,裁剪 80% 宽、80% 高
await scanner.crop(seq, 0.1, 0.1, 0.8, 0.8);
矩形标注、颜色、线条宽度
// 在图片上画红色矩形,线宽 3px
await scanner.annotateRect(seq, 0.1, 0.1, 0.5, 0.3, '#ff0000', 3);
// 蓝色粗线
await scanner.annotateRect(seq, 0.2, 0.2, 0.4, 0.2, '#0066ff', 8);
编辑后的图片通过 edit 事件返回:
scanner.on('edit', image => {
document.querySelector('#preview').src = image.url;
});
Demo 中的裁剪和标注采用拖框模式:点击“裁剪”或“矩形标注”后,直接在大图预览区域拖动选择范围;Demo 会自动把拖框位置换算成 0~1 的相对坐标并调用 SDK。
选择本地图片
SDK 也提供本地图片选择能力。选择本地图片不需要连接插件,本地图片的旋转、裁剪、标注都在浏览器中完成,不调用插件接口。
const images = await scanner.pickLocalImages({
multiple: true,
accept: 'image/*'
});
const image = images[0];
document.querySelector('#preview').src = image.url;
本地图片编辑
本地图片没有插件返回的 seq,所以使用本地编辑方法;编辑结果会直接返回新的图片对象。Demo 中本地图片同样支持拖框裁剪和拖框标注。
const rotated = await scanner.rotateLocalImage(image, 90);
const cropped = await scanner.cropLocalImage(image, 0.1, 0.1, 0.8, 0.8);
const marked = await scanner.annotateLocalImage(image, 0.1, 0.1, 0.5, 0.3, '#ff0000', 3);
document.querySelector('#preview').src = marked.url;
事件列表
| 事件 | 说明 |
|---|---|
open | WebSocket 已连接 |
close | WebSocket 已断开 |
error | WebSocket 错误 |
send | 已发送命令 |
command | 收到命令响应 |
image | 收到扫描图片 |
edit | 收到编辑后的图片 |
image-meta | 收到图片元数据 |
edit-meta | 收到编辑元数据 |
text | 收到非 JSON 文本 |
自定义命令
如果后续插件新增命令,可以直接调用 command,不需要修改 SDK:
const resp = await scanner.command('get_status');
运行 Demo
直接打开:
examples/sdk/nexscanner-sdk-demo.html
或放到任意静态 Web 服务中访问。
注意事项
- SDK 只封装 WebSocket 协议,不直接访问系统扫描接口。
- 插件必须先启动,网页才能连接。
image.url是浏览器临时地址;如果要上传或保存,请使用image.blob或image.bytes。