前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用Javascript通过Web TWAIN协议快速集成扫描仪设备

使用Javascript通过Web TWAIN协议快速集成扫描仪设备

原创
作者头像
用户1935133
修改于 2025-01-23 02:14:49
修改于 2025-01-23 02:14:49
1690
举报

使用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组件

WebScanner前端组件支持有纯Javascript组件、Vue.js组件等方式。我们使用纯Javavscript组件来集成。

下载WebScanner组件

从官网下载纯Javascript组件的Sample演示代码WebScanner-JS-Sample.zip

解压压缩包,解压后的目录结构和文件清单如图:

主目录下:

scripts子目录下

css子目录下

集成WebScanner纯Javascript组件到系统页面

创建测试应用主目录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。

服务组件安装 (Windows平台)

安装服务

解压缩wssService.zip安装包后,以管理员身份运行其中的安装程序wssService.exe。

点击“是”,

安装程序
安装程序

点击“Next”

安装程序
安装程序

点击“Install”,开始安装

安装程序
安装程序

勾选“Launch WebScannerService”,点击“Finish”,启动服务,并完成安装。

启动wssService服务

在Windows服务中,右击 WebScannerService 服务,在弹出菜单中点击“启动”启动服务。

安装程序
安装程序

重启wssService服务

在Windows服务中,右击 WebScannerService 服务,在弹出菜单中点击“重新启动”启动服务。

安装程序
安装程序

停止wssService服务

在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,然后点击“扫描”按钮进行扫描,发现编辑器中可以展示出扫描的图像来了。

文档上传(PHP对接)

需要将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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档