scanonweb
Version:
ScanOnWeb - 扫描控件 JavaScript SDK,用于与本地扫描服务程序通信
558 lines (521 loc) • 15.8 kB
JavaScript
/**
* ScanOnWeb - 扫描控件 JavaScript SDK
* https://www.brainysoft.cn 扫描控件官方网站,如需更多文档帮助请访问官网
* @version 1.0.1
* @author BrainySoft
* @license MIT
*/
/**
* 扫描控件类 - 用于与本地扫描服务程序通信
* @class ScanOnWeb
*/
class ScanOnWeb {
constructor() {
// 扫描配置参数信息,后续扫描仪开始扫描前会根据这个配置信息来进行扫描设置
this.scaner_work_config = {
showUI: false, // 是否显示扫描控件工作界面,如果为false则不显示扫描控件工作界面
dpi_x: 300, // dpi 分辨率x,一般的图像扫描300dpi就够了
dpi_y: 300, // dpi 分辨率y
deviceIndex: 0, // 选中的扫描仪硬件设备id索引,如果有多个扫描仪设备,这个值就是用来选择哪个设备进行扫描的
showDialog: false, // 是否显示设备内置对话框
autoFeedEnable: true, // 是否使用自动进纸器(需要设备支持才能正常工作)
autoFeed: false, // 是否自动装填纸张(需要设备支持才能正常工作)
dupxMode: false, // 是否使用双面扫描模式(需要设备支持才能正常工作)
autoDeskew: false, // 是否使用自动纠偏模式(需要设备支持才能正常工作)
autoBorderDetection: false, // 是否使用自动边框检测(需要设备支持才能正常工作)
colorMode: "RGB", // 色彩模式,RGB为彩色模式,BW是黑白模式 ,GRAY是灰色模式
transMode: "memory", // 数据传输模式,memory,file,native 这三种配置值,默认为memory模式,大部分设备都是使用这种模式
};
this.h5socket = null;
this.imageCount = 0; // 扫描结果图像总数
// 尝试连接websocket服务器,注意连接成功哪个是通过回调实现的
this.tryConnect();
}
/**
* 通过连接多个websocket server端口返回一个可用的websocket连接对象,主要用于防止本地端口被占用的情况
* @param {string[]} wssUrls - WebSocket服务器URL数组
* @returns {Promise} WebSocket连接Promise
*/
getConnectedServer(wssUrls) {
console.log("尝试连接托盘扫描服务websocket服务器...");
return new Promise((resolve, reject) => {
const server = new WebSocket(wssUrls[0]);
server.onopen = () => {
resolve(server);
};
server.onerror = (err) => {
reject(err);
};
}).then(
(server) => {
console.log("连接websocket服务器成功!");
// 找到了可用websocket服务器端口
this.initWebsocketCallback(server);
console.log("尝试获取扫描设备列表...");
// 发送一个获取扫描设备列表的命令,询问本地计算机安装了多少个扫描设备的驱动程序
this.loadDevices();
return server;
},
(err) => {
// 如果连接失败,则尝试连接其他端口
if (wssUrls.length > 1) {
return this.getConnectedServer(wssUrls.slice(1));
}
throw err;
}
);
}
/**
* 尝试检测websocket哪个端口可以成功连接
*/
tryConnect() {
// 以下一共定义了5个websocket端口,如果有端口被占用,则会自动尝试连接下一个端口
const wssUrls = [
"ws://127.0.0.1:1001",
"ws://127.0.0.1:2001",
"ws://127.0.0.1:3001",
"ws://127.0.0.1:4001",
"ws://127.0.0.1:5001",
];
this.getConnectedServer(wssUrls);
}
/**
* 初始化websocket相关的函数绑定
* @param {WebSocket} server - WebSocket服务器实例
*/
initWebsocketCallback(server) {
this.h5socket = server;
this.h5socket.onerror = this.onSocketError.bind(this);
this.h5socket.onmessage = this.onSocketMessage.bind(this);
}
/**
* WebSocket错误处理
* @param {Event} event - 错误事件
*/
onSocketError(event) {
alert("无法连接扫描服务程序,请检查扫描服务程序是否已经启动!");
console.log("WebSocket error: " + event.data);
}
/**
* 判断回调函数是否存在
* @param {Function} f - 要检查的函数
* @returns {boolean} 函数是否存在且为函数类型
*/
isCallbackExist(f) {
if (!f || typeof f === "undefined" || f === undefined) {
return false;
}
return typeof f === "function";
}
/**
* WebSocket消息处理
* @param {MessageEvent} event - WebSocket消息事件
*/
onSocketMessage(event) {
const msg = JSON.parse(event.data);
// console.log(msg);
switch (msg.cmd_type) {
case "getDevicesList": {
// 获取设备信息列表返回结果
if (this.isCallbackExist(this.onGetDevicesListEvent)) {
this.onGetDevicesListEvent(msg);
}
break;
}
case "scanComplete": {
// 扫描完成
this.imageCount = msg.imageCount;
if (this.isCallbackExist(this.onScanFinishedEvent)) {
this.onScanFinishedEvent(msg);
}
break;
}
case "selectScanDevice": {
// 选择扫描设备结果
this.scaner_work_config.deviceIndex = msg.currentIndex; // 当前选中的设备索引
this.scaner_work_config.showDialog = msg.showDialog; // 是否显示设备内置对话框
this.scaner_work_config.autoFeedEnable = msg.autoFeedEnable; // 是否使用自动进纸器(需要设备支持才能正常工作)
this.scaner_work_config.autoFeed = msg.autoFeed; // 是否自动装填纸张(需要设备支持才能正常工作)
this.scaner_work_config.dupxMode = msg.dupxMode; // 是否使用双面扫描模式(需要设备支持才能正常工作)
this.scaner_work_config.autoDeskew = msg.autoDeskew; // 是否使用自动纠偏模式(需要设备支持才能正常工作)
this.scaner_work_config.autoBorderDetection = msg.autoBorderDetection; // 是否使用自动边框检测(需要设备支持才能正常工作)
if (this.isCallbackExist(this.onSelectScanDeviceEvent)) {
this.onSelectScanDeviceEvent(msg);
}
break;
}
case "getImageCount": {
// 获取扫描图片数量
this.imageCount = msg.imageCount;
if (this.isCallbackExist(this.onGetImageCountEvent)) {
this.onGetImageCountEvent(msg);
}
break;
}
case "getAllImage": {
// 获取所有图片
this.imageCount = msg.imageCount;
if (this.isCallbackExist(this.onGetAllImageEvent)) {
this.onGetAllImageEvent(msg);
}
break;
}
case "getImageById": {
// 获取某一页图片的base64编码数据
this.imageCount = msg.imageCount;
if (this.isCallbackExist(this.onGetImageByIdEvent)) {
this.onGetImageByIdEvent(msg);
}
break;
}
case "loadImageFromUrl": {
// 从URL加载图片
this.imageCount = msg.imageCount;
if (this.isCallbackExist(this.onLoadImageFromUrlEvent)) {
this.onLoadImageFromUrlEvent(msg);
}
break;
}
case "rotateImage": {
// 旋转图片
this.imageCount = msg.imageCount;
if (this.isCallbackExist(this.onRotateImageEvent)) {
this.onRotateImageEvent(msg);
}
break;
}
case "getImageSize": {
// 获取图片尺寸
this.imageCount = msg.imageCount;
if (this.isCallbackExist(this.onGetImageSizeEvent)) {
this.onGetImageSizeEvent(msg);
}
break;
}
case "uploadAllImageAsPdfToUrl": {
// 上传pdf图像到指定的URL的回调
if (this.isCallbackExist(this.onUploadAllImageAsPdfToUrlEvent)) {
this.onUploadAllImageAsPdfToUrlEvent(msg);
}
break;
}
case "uploadAllImageAsTiffToUrl": {
// 上传tiff图像到指定的URL的回调
if (this.isCallbackExist(this.onUploadAllImageAsTiffToUrlEvent)) {
this.onUploadAllImageAsTiffToUrlEvent(msg);
}
break;
}
case "uploadJpgImageByIndex": {
// 上传jpg图像到指定的URL的回调
if (this.isCallbackExist(this.onUploadJpgImageByIndexEvent)) {
this.onUploadJpgImageByIndexEvent(msg);
}
break;
}
case "upload": {
this.imageCount = msg.imageCount;
// 用户点击了界面里面的"开始上传"按钮的时间回调
if (this.isCallbackExist(this.onUploadEvent)) {
this.onUploadEvent(msg);
}
break;
}
case "imageEdited": {
// 用户在扫描托盘程序里面对图片进行了编辑操作的回调
if (this.isCallbackExist(this.onImageEditedEvent)) {
this.onImageEditedEvent(msg);
}
break;
}
case "imageDrap": {
// 用户在扫描托盘程序里面对图片进行了拖拽操作的回调
if (this.isCallbackExist(this.onImageDrapEvent)) {
this.onImageDrapEvent(msg);
}
break;
}
}
}
/**
* 通过websocket发送数据给webscoket服务端
* @param {Object} commandData - 要发送的命令数据
*/
sendWebSocketCommand(commandData) {
try {
if (this.h5socket.readyState === 1) {
this.h5socket.send(JSON.stringify(commandData));
} else {
alert(
"发送扫描指令失败!请刷新页面或者检查托盘扫描程序是否已经正常运行!"
);
}
} catch (e) {
alert("发送扫描指令失败!" + e);
}
}
/**
* 设置授权信息
* @param {string} licenseMode - 授权模式
* @param {string} key1 - 授权密钥1
* @param {string} key2 - 授权密钥2
* @param {string} licenseServerUrl - 授权服务器URL
*/
setLicenseKey(licenseMode, key1, key2, licenseServerUrl) {
const cmdObj = {
cmd_type: "setLicenseKey",
licenseMode: licenseMode,
key1: key1,
key2: key2,
url: licenseServerUrl,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 加载所有可用的扫描设备
*/
loadDevices() {
const cmdObj = {
cmd_type: "getDevicesList",
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 设置当前选中的扫描设备id
* @param {number} deviceIndex - 设备索引
*/
selectScanDevice(deviceIndex) {
const cmdObj = {
cmd_type: "selectScanDevice",
deviceIndex: deviceIndex,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 开始扫描
*/
startScan() {
const cmdObj = {
cmd_type: "startScan",
config: this.scaner_work_config,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 清除全部扫描结果
*/
clearAll() {
const cmdObj = {
cmd_type: "clearAll",
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 获取图像总数
*/
getImageCount() {
const cmdObj = {
cmd_type: "getImageCount",
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 获取所有图像
*/
getAllImage() {
const cmdObj = {
cmd_type: "getAllImage",
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 发送指令获取某一页图像到托盘服务
* @param {number} index - 图像索引
*/
getImageById(index) {
const cmdObj = {
cmd_type: "getImageById",
index: index,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 发送指令远程加载服务器端的多页图像到托盘服务
* @param {string} url - 图像URL
*/
loadImageFromUrl(url) {
const cmdObj = {
cmd_type: "loadImageFromUrl",
url: url,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 发送指令旋转某一页图像到托盘服务
* @param {number} index - 图像索引
* @param {number} angle - 旋转角度
*/
rotateImage(index, angle) {
const cmdObj = {
cmd_type: "rotateImage",
index: index,
angle: angle,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 发送指令获取某一页图像的宽度到托盘服务
* @param {number} index - 图像索引
*/
getImageSize(index) {
const cmdObj = {
cmd_type: "getImageSize",
index: index,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 发送指令删除某一页图像到托盘服务
* @param {number} index - 图像索引
*/
deleteImageByIndex(index) {
const cmdObj = {
cmd_type: "deleteImageByIndex",
index: index,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 以pdf格式上传全部图像到服务器端
* @param {string} url - 上传URL
* @param {string} id - 标识ID
* @param {string} desc - 描述信息
*/
uploadAllImageAsPdfToUrl(url, id, desc) {
const cmdObj = {
cmd_type: "uploadAllImageAsPdfToUrl",
url: url,
id: id,
desc: desc,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 以tiff格式上传全部图像到服务器端
* @param {string} url - 上传URL
* @param {string} id - 标识ID
* @param {string} desc - 描述信息
*/
uploadAllImageAsTiffToUrl(url, id, desc) {
const cmdObj = {
cmd_type: "uploadAllImageAsTiffToUrl",
url: url,
id: id,
desc: desc,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 以jpg格式上传某一页图像到服务器端
* @param {string} url - 上传URL
* @param {string} id - 标识ID
* @param {string} desc - 描述信息
* @param {number} index - 图像索引
*/
uploadJpgImageByIndex(url, id, desc, index) {
const cmdObj = {
cmd_type: "uploadJpgImageByIndex",
index: index,
url: url,
id: id,
desc: desc,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 全部图像保存到客户端本地文件
* @param {string} filename - 文件名
*/
saveAllImageToLocal(filename) {
const cmdObj = {
cmd_type: "saveAllImageToLocal",
filename: filename,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 从客户端本地读取图像,通过打开文件对话框选择图像文件
*/
openClientLocalfile() {
const cmdObj = {
cmd_type: "openClientLocalfile",
};
this.sendWebSocketCommand(cmdObj);
}
/**
* ftp上传全部图像文件到服务器端
* @param {string} serverIp - 服务器IP
* @param {number} port - 端口
* @param {string} username - 用户名
* @param {string} password - 密码
* @param {string} serverPath - 服务器路径
* @param {string} filename - 文件名
*/
ftpUploadAllImage(serverIp, port, username, password, serverPath, filename) {
const cmdObj = {
cmd_type: "ftpUploadAllImage",
serverIp: serverIp,
port: port,
username: username,
password: password,
serverPath: serverPath,
filename: filename,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 设置上传按钮是否可见
* @param {boolean} visible - 是否可见
*/
setUploadButtonVisible(visible) {
const cmdObj = {
cmd_type: "setUploadButtonVisible",
visible: visible,
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 设置焦点
*/
setFocus() {
const cmdObj = {
cmd_type: "focus",
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 隐藏窗口
*/
hidden() {
const cmdObj = {
cmd_type: "hidden",
};
this.sendWebSocketCommand(cmdObj);
}
/**
* 关闭websocket连接
*/
closeWebSocket() {
this.h5socket.close();
}
}
// ES6 模块导出
export default ScanOnWeb;
// CommonJS 兼容性导出
if (typeof module !== "undefined" && module.exports) {
module.exports = ScanOnWeb;
}
// UMD 兼容性导出
if (typeof window !== "undefined") {
window.ScanOnWeb = ScanOnWeb;
}