前言
目前web开发技术经过多年发展之后,大浪淘沙,古老的activex、NPAPI等技术都已经被淘汰,甚至连IE浏览器都已经被淘汰了,国内做web前端开发有大量使用vue技术的公司,在日常业务开发里面如果涉及到驱动扫描仪进行图像扫描都找不到太好的解决方案。
受浏览器的安全限定,想要通过前端js或typescript直接去操作客户端的硬件设备,如扫描仪、摄像头、身份证读卡器等都不允许,只能通过开启一个本地websocket中转服务去操作硬件外设,本文介绍的是如何使用scanonweb h5版本实现vue图像扫描。
一、前端开发库sdk获取
点击 https://www.brainysoft.cn/download/clientjs.zip 下载vue 前端sdk库,下载后用开发工具如vscode 打开示例html可以测试了,如下面这样:
二、如何使用
整个前端项目主要依赖一个js文件,即scanonweb.js文件,该文件负责与扫描托盘服务程序进行交互,交互界面可以使用示例程序自带的,也可以根据需要自己进行设计,最好去调用scanonweb.js的方法就可以实现图像扫描了。
主要关键实现代码解析,下面是vue扫描组件的源码:
<template><div class="scanonweb_panel"><div style="height: 20px;background-color:chocolate;"><label style="text-align: center;display: inline-block;width: 100%; font-size: 12px;">扫描参数</label></div><form><div class="block"><label for="showUI">是否显示组件界面:</label><select id="showUI"><option value="true">显示</option><option value="false" selected>不显示</option></select></div><div class="block"><label for="devices">扫描设备:</label><select id="devices"></select></div><div class="block"><label for="dpi_x">设备输入分辨率:</label><input type="text" id="dpi_x" v-model="dpi_x" style="width: 25px;" /> X<input type="text" id="dpi_y" v-model="dpi_y" style="width: 25px;" /></div><div class="block"><label for="showDialog">是否显示内置对话框:</label><select id="showDialog"><option value="true">显示</option><option value="false" selected>不显示</option></select></div><div class="block"><label for="feedEnable">自动进纸模式:</label><select id="feedEnable"><option value="true">是</option><option value="false" selected>否</option></select></div><div class="block"><label for="autoFeed">自动装填纸张:</label><select id="autoFeed"><option value="true">是</option><option value="false" selected>否</option></select></div><div class="block"><label>双面模式:</label><select id="dupxMode"><option value="true">是</option><option value="false" selected>否</option></select></div><div class="block"><label>自动纠偏:</label><select id="autoDeskew"><option value="true">是</option><option value="false" selected>否</option></select></div><div class="block"><label>自动边框检测:</label><select id="autoBorderDetection"><option value="true">是</option><option value="false" selected>否</option></select></div></form></div>
</template>
<script>
module.exports = {data:function() {return {showUI: 'false',devices: '',dpi_x: 300,dpi_y: 300,}},props:{},created: function () {//加载scanonweb.jsthis.scanonweb = new ScanOnWeb();//响应返回扫描设备列表的回调函数this.scanonweb.onGetDevicesListEvent = function (msg) {console.log(msg);var deviceListDom = document.getElementById('devices');//clear devices listdeviceListDom.innerHTML = "";for (var i = 0; i < deviceListDom.childNodes.length; i++) {ardeviceListDomea.removeChild(deviceListDom.options[0]);deviceListDom.remove(0);deviceListDom.options[0] = null;}//add devices infofor (var i = 0; i < msg.devices.length; ++i) {var opt = document.createElement("option");opt.innerHTML = msg.devices[i];if (i == msg.currentIndex) {opt.selected = true;}deviceListDom.appendChild(opt);}}// //响应扫描完成事件this.scanonweb.onScanFinishedEvent = function (msg) {document.getElementById('pdf_viewer').contentWindow.location.reload();}},mounted: function () {},methods: {//开始扫描startScan: function () {if (document.getElementById("devices").selectedIndex == -1) {alert('请先刷新或者选中要使用的扫描设备后再开始扫描!');return;}//以下获取界面中的扫描参数设定this.scanonweb.scaner_work_config.dpi_x = dpi_x.value;this.scanonweb.scaner_work_config.dpi_y = dpi_y.value;this.scanonweb.scaner_work_config.deviceIndex = document.getElementById("devices").selectedIndex;this.scanonweb.scaner_work_config.showDialog = document.getElementById("showDialog").value;this.scanonweb.scaner_work_config.autoFeedEnable = document.getElementById("feedEnable").value;this.scanonweb.scaner_work_config.autoFeed = document.getElementById("autoFeed").value;this.scanonweb.scaner_work_config.dupxMode = document.getElementById("dupxMode").value;this.scanonweb.scaner_work_config.autoDeskew = document.getElementById("autoDeskew").value;this.scanonweb.scaner_work_config.autoBorderDetection = document.getElementById("autoBorderDetection").value;//开始发送扫描指令this.scanonweb.startScan();}}
}
</script>
<style>
.scanonweb_panel {width: 100%;height: 100%;background-color: #fff;
}
</style>
在created事件中初始化scanowneb对象,与扫描托盘服务程序进行连接,读取客户端操作系统已安装的扫描设备列表信息进行显示。
created: function () {//加载scanonweb.jsthis.scanonweb = new ScanOnWeb();//响应返回扫描设备列表的回调函数this.scanonweb.onGetDevicesListEvent = function (msg) {console.log(msg);var deviceListDom = document.getElementById('devices');//clear devices listdeviceListDom.innerHTML = "";for (var i = 0; i < deviceListDom.childNodes.length; i++) {ardeviceListDomea.removeChild(deviceListDom.options[0]);deviceListDom.remove(0);deviceListDom.options[0] = null;}//add devices infofor (var i = 0; i < msg.devices.length; ++i) {var opt = document.createElement("option");opt.innerHTML = msg.devices[i];if (i == msg.currentIndex) {opt.selected = true;}deviceListDom.appendChild(opt);}}
用户在界面选中要使用哪一个扫描设备,确定好扫描分辨率等参数以后,点击扫描按钮触发以下代码执行:
methods: {//开始扫描startScan: function () {if (document.getElementById("devices").selectedIndex == -1) {alert('请先刷新或者选中要使用的扫描设备后再开始扫描!');return;}//以下获取界面中的扫描参数设定this.scanonweb.scaner_work_config.dpi_x = dpi_x.value;this.scanonweb.scaner_work_config.dpi_y = dpi_y.value;this.scanonweb.scaner_work_config.deviceIndex = document.getElementById("devices").selectedIndex;this.scanonweb.scaner_work_config.showDialog = document.getElementById("showDialog").value;this.scanonweb.scaner_work_config.autoFeedEnable = document.getElementById("feedEnable").value;this.scanonweb.scaner_work_config.autoFeed = document.getElementById("autoFeed").value;this.scanonweb.scaner_work_config.dupxMode = document.getElementById("dupxMode").value;this.scanonweb.scaner_work_config.autoDeskew = document.getElementById("autoDeskew").value;this.scanonweb.scaner_work_config.autoBorderDetection = document.getElementById("autoBorderDetection").value;//开始发送扫描指令this.scanonweb.startScan();}}
扫描程序驱动硬件工作完成以后,会给浏览器发送websocket消息,通过以下回调函数接收扫描结果:
// //响应扫描完成事件this.scanonweb.onScanFinishedEvent = function (msg) {document.getElementById('pdf_viewer').contentWindow.location.reload();}
上面的示例是将扫描结果以pdf格式进行了展示,如果需要自己处理扫描结果展示,如向canvas直接绘制的话可以这么处理:
//响应扫描完成事件scanonweb.onScanFinishedEvent = function (msg) {console.log("扫描前:" + msg.imageBeforeCount + " 扫描后:" + msg.imageAfterCount);//以下代码用于将新增的扫描图像从扫描服务程序中取回for (var i = msg.imageBeforeCount; i < msg.imageAfterCount; i++) {scanonweb.getImageById(i);}}//响应获取某一页图像的回调函数scanonweb.onGetImageByIdEvent = function (msg) {var imageListDom = document.getElementById('imageList');var imageDom = document.createElement("img");imageDom.width = 300;imageDom.height = 300;imageDom.src = "data:image/jpg;base64," + msg.imageBase64;imageListDom.appendChild(imageDom);}
有时对扫描结果需要进行裁剪编辑处理,可以通过双击扫描托盘服务程序打开扫描结果编辑界面,里面有旋转、裁剪、魔术棒、色彩填充、去黑边等各种图像编辑处理功能,界面如下:
图像都处理好以后,可以通过以下代码上传扫描结果到服务器端保存:
//按照jpg格式上传所有图像function uploadAllImageAsJpgFormat() {var uploadUrl = 'http://localhost:8080/uploadjpg';for (imageIndex=0;imageIndex<scanonweb.imageCount;imageIndex++){scanonweb.uploadJpgImageByIndex(uploadUrl,'1234','test',imageIndex);} }//按照pdf格式上传所有图像function uploadAllImageAsPdfFormat(){scanonweb.uploadAllImageAsPdfToUrl('http://localhost:8080/upload','1234','test'); }//按照tiff格式上传所有图像function uploadAllImageAsTiffFormat(){scanonweb.uploadAllImageAsTiffToUrl('http://localhost:8080/upload','1234','test'); }
可以将多页扫描结果按多个单页jpg图像格式进行上传,也可以将多页扫描结果直接按单个pdf格式或者tiff图像格式进行上传,后台代码就是普通的接收文件上传的代码,上传图像的时候可以传递一些额外的参数,如图像关联的业务主键id信息等,后台在保存图像数据的同时可以关联业务数据记录。