使用Javascript通过Web TWAIN协议快速集成扫描仪设备
由于项目需求,需要开发在Windows下与Linux下扫描功能,Linux主要是信创的两个系统(UOS、麒麟),研究了一下发现,Windows使用Twain协议与扫描仪通讯,Linux使用的是Sane协议与扫描仪通讯,找到Twain协议和Sane协议的标准文档,英文的,都有大几百页,项目一个月内要求上线,明显没时间慢慢研究,于是在网上找了一番,发现了WebScanner这个第三方组件,这个组件可以支持通过标准扫描协议(Twain、Sane)连接各类扫描硬件,兼容Windows及Linux系统,适配不同CPU指令集(x86、Arm、Loongarch、Mips等),而且不同平台不需要重复适配,一次集成即可完成Twain、Sane协议及不同操作系统的适配实现Web页面上所见即所得的扫描集成,真是太爽了。通过使用这个组件,1、2天内就完成了项目的扫描功能,简直不要太轻松!!那么话不多说,下面简单介绍一下WebScanner扫描组件如何使用。
WebScanner网站提供了在线体验DEMO,可以直接访问DEMO页面进行体验。
如图中所示,组件提供扫描仪设备加载连接、执行扫描、web端编辑器(可展示和编辑扫描到的图像内容)、保存结果文档(保存到本地、保存到服务器)等功能,能满足大部分常规需求,具体可参考官网介绍 。
如图所示,就是WebScanner的架构,主要由WSS Front Component和WSS Service两个组件组成。
WSS Front Component是WebScanner前端组件,运行与浏览器中,负责与WSS Service通信、以及文档展示与编辑、下载上传保存等功能。
WSS Service是WebScanner服务组件,作为系统服务进行运行(Windows服务或Linux服务),负责通过TWAIN/SANE协议与扫描仪设备通讯,控制扫描过程;以及与服务器通信提交上传文档等功能。
WebScanner前端组件支持有纯Javascript组件、Vue.js组件等方式。我们使用纯Javavscript组件来集成。
从官网下载纯Javascript组件的Sample演示代码WebScanner-JS-Sample.zip
解压压缩包,解压后的目录结构和文件清单如图:
主目录下:
scripts子目录下
css子目录下
创建测试应用主目录test,在test目录下新建测试页面test.html;
引入需要的javascript文件(依赖的文件从Sample应用中copy过来);
<script type="text/javascript" src="scripts/jquery.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script type="text/javascript" src="scripts/pdf/pdf.js"></script>
<script type="text/javascript" src="scripts/pdf/pdf.worker.js"></script>
<script type="text/javascript" src="scripts/pdf/jspdf.umd.min.js"></script>
<script type="text/javascript" src="scripts/tui/tui-image-editor-config.js"></script>
<script type="text/javascript" src="scripts/tui/tui-color-picker.js"></script>
<script type="text/javascript" src="scripts/tui/tui-image-editor.js"></script>
<script type="text/javascript" src="scripts/webscan.min.js"></script>
<script type="text/javascript" src="scripts/sample.js"></script>
引入需要的css文件;
<link href="css/tui/tui-color-picker.css" type="text/css" rel="stylesheet">
<link href="css/tui/tui-image-editor.css" type="text/css" rel="stylesheet">
<link href="css/sample.css" type="text/css" rel="stylesheet">
<link href="css/webscan.min.css" type="text/css" rel="stylesheet">
<link rel="stylesheet" href="https://code.jquery.com/ui/1.14.1/themes/base/jquery-ui.css">
在body中间加入如下代码:
<div id="webscanId"></div>
扫描仪选择框
<select id="sources" ></select>
扫描按钮
<button type="button" onclick="scan()">扫描</button>
id为webscanId的div是用于web扫描仪编辑器容器的,id将被传给WebScanner组件用于初始化编辑器组件,编辑器和编辑器的工具栏将在容器中渲染。
id为sources的列表控件用于加载和展示当前电脑所支持的扫描仪设备清单。
扫描按钮调用WebScanner组件接口对扫描仪设备进行扫描,并将扫描返回的图像加入到编辑器中显示。
在body中间加入如下javascript控制代码进行WebScanner组件初始化和设备加载处理:
<script type="text/javascript">
const myscan=new WebScan();
myscan.init(
{
"editorId":"webscanId",
"wssKey":"正式的wssKey",
}
);
console.info(myscan);
vLoadDevices();
async function vLoadDevices(){
selectSources = document.getElementById("sources");
selectSources.options.length = 0;
sourceCount = sources.length;
var response = myscan.getSourceNames();
if (response) {
let sources = response;
if (sources.length <= 0) {
selectSources.options.add(new Option("没有检测到任何扫描仪", "没有检测到任何扫描仪"));
return;
}
for (let i = 0; i < sources.length; i++) {
selectSources.options.add(new Option(sources[i], sources[i]));
}
if (sources.length > 0) {
let val = selectSources[selectSources.selectedIndex].value;
var resp = await myscan.selectDevice(val);
if (resp != "success"){
alert(resp);
}
}
}
};
</script>
完整代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TEST</title>
<script type="text/javascript" src="scripts/jquery.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script type="text/javascript" src="scripts/pdf/pdf.js"></script>
<script type="text/javascript" src="scripts/pdf/pdf.worker.js"></script>
<script type="text/javascript" src="scripts/pdf/jspdf.umd.min.js"></script>
<script type="text/javascript" src="scripts/tui/tui-image-editor-config.js"></script>
<script type="text/javascript" src="scripts/tui/tui-color-picker.js"></script>
<script type="text/javascript" src="scripts/tui/tui-image-editor.js"></script>
<script type="text/javascript" src="scripts/webscan.min.js"></script>
<script type="text/javascript" src="scripts/sample.js"></script>
<link href="css/tui/tui-color-picker.css" type="text/css" rel="stylesheet">
<link href="css/tui/tui-image-editor.css" type="text/css" rel="stylesheet">
<link href="css/sample.css" type="text/css" rel="stylesheet">
<link href="css/webscan.min.css" type="text/css" rel="stylesheet">
<link rel="stylesheet" href="https://code.jquery.com/ui/1.14.1/themes/base/jquery-ui.css">
</head>
<body>
<div style="display: flex;">
<div id="webscanId"></div>
<div style="width: 360px;">
<div id="webscanId"></div>
扫描仪选择框
<select id="sources" onchange="deviceChange()"></select>
扫描按钮
<button type="button" onclick="scan()">扫描</button>
</div>
</div>
<script type="text/javascript">
const myscan=new WebScan();
myscan.init(
{
"editorId":"webscanId",
"wssKey":"eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJ0eXBlIjoidHJpYWwiLCJjb21wYW55IjoiXHU3ZjUxXHU4ZDM3XHU0ZTRiXHU1YmI2IiwiY29udGFjdFBlcnNvbiI6Ilx1NWYyMFx1NGUwOSIsImNvbnRhY3RQaG9uZSI6Ilx1NWYyMFx1NGUwOSIsIm1vYmlsZSI6IjEzODE3NjIyMjk4IiwiZW1haWwiOiJsaXViaW5nZkAxNjMuY29tIiwiTUFDIjoiU0tERU0zRDNLTk1TIiwiZXhwIjoxNzU0MDE3MzgyLCJkZWFkbGluZSI6MTc1NDAxNzM4Mn0.tjvV-jmfnpJlXeKt_o8EGFMLJN2KLVKNQHBVQxuEuzA", //这是30天试用版license,如果你有正式版license可进行替换
}
);
console.info(myscan);
vLoadDevices();
async function vLoadDevices(){
selectSources = document.getElementById("sources");
selectSources.options.length = 0;
sourceCount = sources.length;
var response = myscan.getSourceNames();
if (response) {
let sources = response;
if (sources.length <= 0) {
selectSources.options.add(new Option("没有检测到任何扫描仪", "没有检测到任何扫描仪"));
return;
}
for (let i = 0; i < sources.length; i++) {
selectSources.options.add(new Option(sources[i], sources[i]));
}
if (sources.length > 0) {
let val = selectSources[selectSources.selectedIndex].value;
var resp = await myscan.selectDevice(val);
if (resp != "success"){
alert(resp);
}
}
}
};
</script>
</body>
<html>
用chrome浏览器打开test.html页面,提示没有安装服务:
点击提示中的下载链接下载WebScanner Service安装包wssService.zip。
解压缩wssService.zip安装包后,以管理员身份运行其中的安装程序wssService.exe。
点击“是”,
点击“Next”
点击“Install”,开始安装
勾选“Launch WebScannerService”,点击“Finish”,启动服务,并完成安装。
在Windows服务中,右击 WebScannerService 服务,在弹出菜单中点击“启动”启动服务。
在Windows服务中,右击 WebScannerService 服务,在弹出菜单中点击“重新启动”启动服务。
在Windows服务中,右击 WebScannerService 服务,在弹出菜单中点击“停止”停止服务。
服务安装并启动好后,继续测试集成页面test.html,在浏览器中刷新test.html页面,可以看到扫描仪设备的驱动已经加载出来了。
这里加了3个扫描仪驱动 EPSON DS057W 、EPSON DS-570WII、TWAIN2 Software Scanner。2个EPSON扫描仪是我以前测试用的,现在没有连接到真实设备上,用不了,所以在刷新页面时提示该设备不在线。
还有一个TWAIN2 Software Scanner其实是TWAIN2官方用于测试的TWAIN协议虚拟扫描设备,可以进行扫描。如果你也想我一样没有连接到真实的扫描仪设备,可以用这个来虚拟扫描仪来调试程序。
虚拟扫描仪程序:
https://github.com/twain/twain-toolkit/releases/download/v2.5.0/twacker_020500.zip
这里我们选择TWAIN2 Software Scanner,然后点击“扫描”按钮进行扫描,发现编辑器中可以展示出扫描的图像来了。
需要将WebScanner组件扫描的到的文档上传到服务器保存起来,便于业务系统在需要的地方调用展示。
修改test.html ,添加上传按钮和上传处理javascript,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TEST</title>
<script type="text/javascript" src="scripts/jquery.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script type="text/javascript" src="scripts/pdf/pdf.js"></script>
<script type="text/javascript" src="scripts/pdf/pdf.worker.js"></script>
<script type="text/javascript" src="scripts/pdf/jspdf.umd.min.js"></script>
<script type="text/javascript" src="scripts/tui/tui-image-editor-config.js"></script>
<script type="text/javascript" src="scripts/tui/tui-color-picker.js"></script>
<script type="text/javascript" src="scripts/tui/tui-image-editor.js"></script>
<script type="text/javascript" src="scripts/webscan.min.js"></script>
<script type="text/javascript" src="scripts/sample.js"></script>
<link href="css/tui/tui-color-picker.css" type="text/css" rel="stylesheet">
<link href="css/tui/tui-image-editor.css" type="text/css" rel="stylesheet">
<link href="css/sample.css" type="text/css" rel="stylesheet">
<link href="css/webscan.min.css" type="text/css" rel="stylesheet">
<link rel="stylesheet" href="https://code.jquery.com/ui/1.14.1/themes/base/jquery-ui.css">
</head>
<body>
<div style="display: flex;">
<div id="webscanId"></div>
<div style="width: 360px;">
<div id="webscanId"></div>
扫描仪选择框
<select id="sources" onchange="deviceChange()"></select>
扫描按钮
<button type="button" onclick="scan()">扫描</button>
<button type="button" onclick="uploadDocToServer()">上传</button>
</div>
</div>
<script type="text/javascript">
const myscan=new WebScan();
myscan.init(
{
"editorId":"webscanId",
"wssKey":"eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJ0eXBlIjoidHJpYWwiLCJjb21wYW55IjoiXHU3ZjUxXHU4ZDM3XHU0ZTRiXHU1YmI2IiwiY29udGFjdFBlcnNvbiI6Ilx1NWYyMFx1NGUwOSIsImNvbnRhY3RQaG9uZSI6Ilx1NWYyMFx1NGUwOSIsIm1vYmlsZSI6IjEzODE3NjIyMjk4IiwiZW1haWwiOiJsaXViaW5nZkAxNjMuY29tIiwiTUFDIjoiU0tERU0zRDNLTk1TIiwiZXhwIjoxNzU0MDE3MzgyLCJkZWFkbGluZSI6MTc1NDAxNzM4Mn0.tjvV-jmfnpJlXeKt_o8EGFMLJN2KLVKNQHBVQxuEuzA", //这是30天试用版license,如果你有正式版license可进行替换
}
);
console.info(myscan);
vLoadDevices();
async function vLoadDevices(){
selectSources = document.getElementById("sources");
selectSources.options.length = 0;
sourceCount = sources.length;
var response = myscan.getSourceNames();
if (response) {
let sources = response;
if (sources.length <= 0) {
selectSources.options.add(new Option("没有检测到任何扫描仪", "没有检测到任何扫描仪"));
return;
}
for (let i = 0; i < sources.length; i++) {
selectSources.options.add(new Option(sources[i], sources[i]));
}
if (sources.length > 0) {
let val = selectSources[selectSources.selectedIndex].value;
var resp = await myscan.selectDevice(val);
if (resp != "success"){
alert(resp);
}
}
}
};
function uploadDocToServer() {
let serverCustomHttpHeaders = {}
let resp = myscan.HTTPUploadAllThroughPostAsPDF("test.pdf" , serverCustomHttpHeaders, "http://192.168.0.131","/testupload.php" );
console.log(resp)
alert(resp.data)
}
</script>
</body>
<html>
其中关键语句是
myscan.HTTPUploadAllThroughPostAsPDF("test.pdf" , serverCustomHttpHeaders, "http://192.168.0.123","/testupload.php" )
调用组件HTTPUploadAllThroughPostAsPDF方法将编辑器中文档合并转化为pdf格式并提交上传到URL: http://192.168.0.123/upload.php。这个url链接是我们要在服务端实现的处理上传action。
WSS (Web Scanner Service)是以MultipartFile格式将文件提交到目标URL,那我们以这种格式进行接收处理就可以了。
另外提交时还可以携带自定义的header信息(serverCustomHttpHeaders),用于server端认证或携带业务数据等。这里我们携带了系统的jwtToken用于认证作用。
testupload.php代码如下,部署到192.168.0.123 PHP环境上。
<?php
$file = $_FILES['file'];
// 移动文件到指定目录
$destination = '/tmp/' . basename($file['name']);
$respData = array("status"=>"fail");
if (move_uploaded_file($file['tmp_name'], $destination)) {
// 保存成功,返回生成的文档url
$url = "http://192.168.0.131/getdoc/". $file['name'];
$respData = array("status"=>"success","url" => $url );
} else {
// 保存失败,返回失败状态
$respData = array("status"=>"fail");
}
echo json_encode($respData);
?>
刷新test.html页面再次测试,点击“扫描”按钮进行扫描,在点击“上传”保存到服务器。
如图可见,获取到了服务器保存文档生成的文档URL,业务系统即可将此URL保存到业务表单中,在需要展示的地方调用展示即可。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有