本文描述如何通过网页驱动扫描仪、高拍仪等图像扫描设备进行图像扫描,扫描结果经编辑修改后以pdf压缩格式上传到后台java程序中进行服务器端落盘保存。
图像扫描上传如文字描述顺序所介绍,先要驱动扫描设备工作,进行纸张数据的光学扫描操作形成图像数据,之后对扫描结果进行剪切、旋转等编辑处理工作,最后的步骤是将加工处理好的结果上传到服务器端进行保存,这里面涉及到前端网页编程、后台服务器端编程等工作,以下按顺序介绍前后台如何具体是如何实现的。
一、准备工作
客户端计算机如果想进行图像扫描,首先需要连接硬件图像扫描设备,一般通过USB数据线与客户端电脑连接,当然如果局域网环境内有其他扫描仪设备,也可以使用局域网内的共享扫描设备,以上两种方式均需要安装扫描仪硬件设备对应的驱动程序,可以根据硬件设备的品牌型号到对应厂家下载驱动程序在客户端电脑安装配置。如果驱动程序有多种类型,选择包含twain驱动程序的下载使用。
二、设计交互网页界面
用户的电脑不一定只连接一台扫描设备,想让用户进行图像扫描时到底使用哪一台扫描设备需要有web交互界面供用户选择确定,另外在系统内有多个驱动程序的情况下windows并不能识别出来当前哪个设备处于可用状态,哪些设备已经断开与计算机的连接或者网络,所以需要由用户选择确认一下到底要使用哪个设备进行扫描,类似的,还有扫描时的分辨率DPI设置、扫描后图像是彩色还是灰度或黑白色的设置等等,这些都需要设计UI界面供用户设定。
这里给出读取系统连接的扫描仪并填充到下拉列表的关键核心代码示例:
<form>
。。。
<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" value="300" style="width: 25px;" /> X
<input type="text" id="dpi_y" value="300" 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>
<script src="./scanonweb.js" type="text/javascript"></script>
<script type="text/javascript">
var scanonweb = new ScanOnWeb();
//响应返回扫描设备列表的回调函数
scanonweb.onGetDevicesListEvent = function (msg) {
var deviceListDom = document.getElementById('devices');
//clear devices list
deviceListDom.innerHTML = "";
for (var i = 0; i < deviceListDom.childNodes.length; i++) {
ardeviceListDomea.removeChild(deviceListDom.options[0]);
deviceListDom.remove(0);
deviceListDom.options[0] = null;
}
//add devices info
for (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);
}
}
上面的代码自动读取客户端计算机已经安装的扫描设备信息并自动填充到下拉列表框里面供用户选择使用。
三、驱动扫描设备进行图像扫描
前端网页添加“扫描”按钮,点击事件执行javascript代码去驱动扫描仪进行图像扫描,关键核心代码如下:
//开始扫描命令
function startScan() {
if (document.getElementById("devices").selectedIndex == -1) {
alert('请先刷新或者选中要使用的扫描设备后再开始扫描!');
return;
}
//以下获取界面中的扫描参数设定
scanonweb.scaner_work_config.dpi_x = document.getElementById("dpi_x").value;
scanonweb.scaner_work_config.dpi_y = document.getElementById("dpi_y").value;
scanonweb.scaner_work_config.deviceIndex = document.getElementById("devices").selectedIndex;
scanonweb.scaner_work_config.showDialog = document.getElementById("showDialog").value;
scanonweb.scaner_work_config.autoFeedEnable = document.getElementById("feedEnable").value;
scanonweb.scaner_work_config.autoFeed = document.getElementById("autoFeed").value;
scanonweb.scaner_work_config.dupxMode = document.getElementById("dupxMode").value;
scanonweb.scaner_work_config.autoDeskew = document.getElementById("autoDeskew").value;
scanonweb.scaner_work_config.autoBorderDetection = document.getElementById("autoBorderDetection").value;
//开始发送扫描指令
scanonweb.startScan();
}
此时用户在网页里面点击扫描按钮触发该函数执行后,扫描仪即可开始进行图像扫描,扫描结果可以通过scanonweb的托盘服务程序进行所见即所得的编辑处理,如:
上面的示例是演示了选中某个区域后进行打马赛克处理,选区内的内容已经变成了马赛克。
四、将图像处理结果上传到服务器端保存
扫描后的图像最终一般都会上传到服务器端进行保存,如果为了预览查看方便,可以使用pdf格式将扫描图像上传到服务器端后进行保存,以下是示例代码:
//按照pdf格式上传所有图像
function uploadAllImageAsPdfFormat(){
scanonweb.uploadAllImageAsPdfToUrl('http://localhost:8080/uploadDemo/fileUpload','1234','test');
}
服务器端接收的示例代码,以java为例:
package cn.brainysoft.uploaddemo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import org.json.JSONObject;
@WebServlet("/fileUpload")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String SAVE_DIR = "uploadFiles";
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取字段数据
String imageCount = request.getParameter("imageCount");
String id = request.getParameter("id");
String desc = request.getParameter("desc");
//输出到控制台
System.out.println("imageCount: " + imageCount);
System.out.println("id: " + id);
System.out.println("desc: " + desc);
//获取文件数据
Part filePart = request.getPart("image");
String fileName = getFileName(filePart);
InputStream fileContent = filePart.getInputStream();
//保存文件到硬盘
String appPath = request.getServletContext().getRealPath("");
String savePath = appPath + File.separator + SAVE_DIR;
File fileSaveDir = new File(savePath);
if (!fileSaveDir.exists()) {
fileSaveDir.mkdir();
}
String filePath = savePath + File.separator + fileName;
FileOutputStream outStream = new FileOutputStream(filePath);
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = fileContent.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
outStream.close();
fileContent.close();
System.out.println("文件保存路径:"+filePath);
//构造返回的json数据
Map<String, String> result = new HashMap<String, String>();
result.put("url", request.getContextPath() + "/" + SAVE_DIR + "/" + fileName);
JSONObject json = new JSONObject(result);
String jsonString = json.toString();
//设置返回的content type为json
response.setContentType("application/json");
//将json数据写入response
response.getWriter().write(jsonString);
}
//获取上传文件的文件名
private String getFileName(final Part part) {
final String partHeader = part.getHeader("content-disposition");
for (String content : partHeader.split(";")) {
if (content.trim().startsWith("filename")) {
return content.substring(content.indexOf('=') + 1).trim()
.replace("\"", "");
}
}
return null;
}
}
上面的示例代码中将收到的pdf图像数据写入硬盘后返回给前端js后续浏览器请求查看时的url路径,具体存盘时的文件名怎么命名大家可以根据自己的需要去计算生成,一般前端收到服务器返回的pdf文件url路径后会通过ajax写在数据库里面保存,例如:
//响应上传pdf图像数据的回调函数
scanonweb.onUploadAllImageAsPdfToUrlEvent = function (msg) {
console.log("上传pdf图像数据到服务器端的响应结果:" + msg);
if (msg.uploadResult) {
//将msg.uploadResult转换为json对象
var uploadResult = JSON.parse(msg.uploadResult);
console.log("上传pdf图像数据保存到服务器端后的请求url地址:" + uploadResult.url);
window.open("http://localhost:8080"+uploadResult.url);
}
}
以上示例较为零散,完整的前端示例代码可以从这里找到: https://www.brainysoft.cn/download/clientjs.zip
后台servlet接收代码完整工程压缩包地址:https://www.brainysoft.cn/download/servletUploadDemo.zip