当前位置: 首页 > news >正文

网页扫描图像并以pdf格式上传到服务器端

本文描述如何通过网页驱动扫描仪、高拍仪等图像扫描设备进行图像扫描,扫描结果经编辑修改后以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 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);}}

上面的代码自动读取客户端计算机已经安装的扫描设备信息并自动填充到下拉列表框里面供用户选择使用。

三、驱动扫描设备进行图像扫描

前端网页添加“扫描”按钮,点击事件执行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为jsonresponse.setContentType("application/json");//将json数据写入responseresponse.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

相关文章:

网页扫描图像并以pdf格式上传到服务器端

本文描述如何通过网页驱动扫描仪、高拍仪等图像扫描设备进行图像扫描&#xff0c;扫描结果经编辑修改后以pdf压缩格式上传到后台java程序中进行服务器端落盘保存。图像扫描上传如文字描述顺序所介绍&#xff0c;先要驱动扫描设备工作&#xff0c;进行纸张数据的光学扫描操作形成…...

Airbyte入门

Airbyte 后端技术栈Java 17框架&#xff1a;JerseyAPI&#xff1a; OAS3数据库&#xff1a;PostgreSQL单元和E2E测试&#xff1a;JUnit 5编排&#xff1a;Temporal连接器技术栈连接器可以用任何语言编写。但是&#xff0c;最常见的语言是&#xff1a;Python3.9.0Java 17前端技术…...

研究人员在野外发现大量的信息窃取者 “Stealc “的样本

一个名为Stealc的新信息窃取者正在暗网上做广告&#xff0c;它可能成为其他同类恶意软件的一个值得竞争的对象。 "SEKOIA在周一的一份报告中说&#xff1a;"威胁行为者将Stealc作为一个功能齐全、随时可用的窃取者&#xff0c;其开发依赖于Vidar、Raccoon、Mars和Re…...

数据结构——复杂度讲解(2)

作者&#xff1a;几冬雪来 时间&#xff1a;2023年2月22日 内容&#xff1a;数据结构复杂度讲解 目录 前言&#xff1a; 复杂度讲解&#xff08;2&#xff09;&#xff1a; 1.空间复杂度是什么&#xff1a; 2.空间复杂度讲解&#xff1a; 结尾&#xff1a; 前言&#x…...

【LeetCode】任务调度器 [M](贪心)

621. 任务调度器 - 力扣&#xff08;LeetCode&#xff09; 一、题目 给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行&#xff0c;并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间&…...

Spring代理模式——静态代理和动态代理

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

Anaconda和PyCharm的一些安装问题和命令

今天更新了Windows上的Anaconda到2.3.2&#xff0c;PyCharm到2022.3。 ——发现是纯纯的犯贱orz。出了一堆问题。在这里记录一下供后来者参考。 Anaconda安装 将.\anaconda3\Scripts 和.\anaconda3\Library\bin添加到系统环境变量中。 新建环境的目录在.\anaconda3\envs下 N…...

sql优化建议

对查询进行优化&#xff0c;应尽量避免全表扫描&#xff0c;首先应考虑在 where 及 order by 涉及的列上建立索引。 应尽量避免在 where 子句中使用!或<>操作符&#xff0c;否则将引擎放弃使用索引而进行全表扫描。 应尽量避免在 where 子句中对字段进行 null 值判断&a…...

google hacker语句

哎&#xff0c;我就是沾边&#xff0c;就是不打实战(&#xffe3;o&#xffe3;) . z Z 文章目录前言一、什么是谷歌Docker&#xff1f;二、受欢迎的谷歌docker语句谷歌docker的例子日志文件易受攻击的 Web 服务器打开 FTP 服务器SSH私钥电子邮件列表实时摄像机MP3、电影和 PDF…...

Spring AOP

Spring AOP 文章目录Spring AOP1.概念1.面向切面编程2.AOP的目的3.AOP实现的分类4.AOP 术语2. Spring AOP的特性1.能力与目标2.AOP机制1.理解SpringAOP的代理2.AOP代理类的自调用代码的粒度如何让自调用走代理&#xff1f;3.Enabling AspectJ Support3. 定义切面与切点1. 声明切…...

【消费战略方法论】认识消费者的恒常原理(一):消费者稳态平衡原理

“消费战略”是塔望咨询基于大量的战略与营销实践经验结合心理学、经济学、传播学等相关专业学科的知识应用进行提炼与创造形成的战略方法体系。消费战略强调以消费者为导向&#xff0c;进行企业、品牌战略、品牌营销的制订和落地&#xff0c;企业经营的每个环节和输出的每个动…...

python居然能语音控制电脑壁纸切换,只需60行代码

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 家在日常的电脑使用中&#xff0c;都会有自己喜爱类型的桌面 单纯的桌面有时候会让人觉得单调 今天&#xff0c;就由我带领大家只用60行代码打造一款语音壁纸切换器程序&#xff0c; 让大家能够通过语音的方式来控制电脑去…...

内存泄露定位手段(c语言hook malloc相关方式)

如何确定有内存泄露问题&#xff0c;如何定位到内存泄露位置&#xff0c;如何写一个内存泄漏检测工具&#xff1f; 1&#xff1a;概述 内存泄露本质&#xff1a;其实就是申请调用malloc/new&#xff0c;但是释放调用free/delete有遗漏&#xff0c;或者重复释放的问题。 内存…...

STM32 CAN波特率计算

STM32 CAN波特率计算简介CAN总线收发&#xff0c;中断方式接收配置代码部分reference简介 CAN通信帧共分为数据帧、远程帧、错误帧、过载帧和帧间隔&#xff0c;本文这里以数据帧为例。 显性电平对应逻辑0&#xff0c;CAN_H和CAN_L之差为2.5V左右。而隐性电平对应逻辑1&#x…...

C/C++ 中#define 的妙用,让代码更美一些

C/C 中#define 的妙用&#xff0c;让代码更美一些 flyfish 1 数值类型输出易读的字符串形式 例如使用enum定义一些错误值&#xff0c;想要将数值类型的错误&#xff0c;输出易读的字符串形式 重要的一句代码 #define MAKE_PAIR(val) std::make_pair(val, #val)可以看到 #va…...

Linux文件系统操作与磁盘管理

查看磁盘和目录的容量 使用 df 命令查看磁盘的容量 df在实验楼的环境中你将看到如下的输出内容&#xff1a; 但在实际的物理主机上会更像这样&#xff1a; 物理主机上的 /dev/sda2 是对应着主机硬盘的分区&#xff0c;后面的数字表示分区号&#xff0c;数字前面的字母 a 表示…...

【Python】批量采集原神表情包~

嗨害大家好鸭~我是小熊猫(✿◡‿◡) 最近迷上了原神&#xff0c; 不自觉中就很喜欢保存广大旅行者制作的表情包~ 真的很有意思诶~ 源码资料电子书:点击此处跳转文末名片获取 一个个保存的话&#xff0c;好像效率很低嘛… 那我就发挥我小熊猫的老本行直接给把他们全部采集下…...

C语言基本语法注释类型关键字

C 基本语法 标识符 给变量所取的名字叫变量名&#xff0c;定义变量的名字需要遵循标识符的命名规则。 标识符是用来标识变量、符号常量、数组、函数、文件等名字的有效字符序列。 标识符的命名规则&#xff1a; 1.只能由字母、数字和下划线组成&#xff08;例如&#xff1a…...

【C ++】C++入门知识(二)

C入门&#xff08;二&#xff09; 作者&#xff1a;小卢 专栏&#xff1a;《C》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 1.引用 1.1.引用的概念及应用 引用&#xff08;&&#xff09; 引用不是新定义一个变量&#xff0…...

qt qchart学习

Qt Charts主要由QChartView、QChart、QLegend图例、坐标轴(由QAbstractAxis子类实现)、**数据源(由QAbstractSeries子类实现)**等组成使用QChart的前期准备1. Qt5.9及以上版本&#xff1b;2. .pro文件中添加QT charts3. 在使用QChart的各个控件之前&#xff0c;引用头文件并必…...

超低功耗电池电压监控电路设计:从LM324到LPV324的硬件方案优化

1. 项目概述与核心需求解析在捣鼓各种电池供电的电子设备时&#xff0c;无论是自己做的无线传感器节点、便携式小工具&#xff0c;还是给孩子改装的玩具&#xff0c;有一个问题总是绕不开&#xff1a;你怎么知道电池快没电了&#xff1f;总不能每次都等到设备彻底罢工&#xff…...

Arduino ADC自检:用RC电路诊断模数转换器故障

1. 项目概述&#xff1a;当你的体重秤开始“说谎”你有没有遇到过这样的情况&#xff1a;站上家里的电子体重秤&#xff0c;屏幕上跳出来的数字让你瞬间怀疑人生&#xff1f;要么是轻得离谱&#xff0c;要么是重得吓人&#xff0c;更诡异的是&#xff0c;它可能只在两个固定的、…...

对比按量计费与Token Plan套餐的实际成本差异

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 对比按量计费与Token Plan套餐的实际成本差异 在构建和运营基于大模型的应用时&#xff0c;成本控制是一个核心的工程考量。Taotok…...

原神私服新纪元:KCN-GenshinServer图形化服务端全功能解析

原神私服新纪元&#xff1a;KCN-GenshinServer图形化服务端全功能解析 【免费下载链接】KCN-GenshinServer 基于GC制作的原神一键GUI多功能服务端。 项目地址: https://gitcode.com/gh_mirrors/kc/KCN-GenshinServer 你是否曾想过拥有一个完全由自己掌控的提瓦特大陆&am…...

从《吃豆人》到开放世界:聊聊Unity Navigation里Agent Radius和Cost的那些‘潜规则’

从《吃豆人》到开放世界&#xff1a;Unity Navigation中Agent Radius与Cost的隐藏逻辑1980年诞生的《吃豆人》用简单的迷宫路径定义了早期游戏AI的移动规则——幽灵们沿着固定路线巡逻&#xff0c;遇到转角时随机选择方向。这种设计在当时堪称革命性&#xff0c;但以今天的标准…...

自然语言处理的实战项目:从0到1搭建属于自己的文本分类系统

对于软件测试从业者而言&#xff0c;日常工作中我们每天都会接触大量的文本数据&#xff1a;缺陷管理系统中的bug描述、测试用例的步骤说明、用户反馈的问题报告、需求文档的规格描述&#xff0c;甚至是接口返回的异常信息文本。这些非结构化文本往往隐含着关键业务信息&#x…...

终极指南:三步搞定Windows系统安卓APK文件安装,告别模拟器时代

终极指南&#xff1a;三步搞定Windows系统安卓APK文件安装&#xff0c;告别模拟器时代 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 还在为电脑无法直接运行手机应用…...

SMUDebugTool:AMD Ryzen处理器深度调试与性能调优完全指南

SMUDebugTool&#xff1a;AMD Ryzen处理器深度调试与性能调优完全指南 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https:…...

ComfyUI-WD14-Tagger:AI智能图像标签提取的终极完整指南

ComfyUI-WD14-Tagger&#xff1a;AI智能图像标签提取的终极完整指南 【免费下载链接】ComfyUI-WD14-Tagger A ComfyUI extension allowing for the interrogation of booru tags from images. 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-WD14-Tagger 在AI图像…...

AI算法工程师必学的Python库:这10个库,AI开发必备

对于软件测试从业者来说&#xff0c;随着人工智能技术在测试领域的渗透越来越深——从自动化测试用例生成到缺陷智能预测&#xff0c;从测试结果分析到测试环境智能化调度&#xff0c;掌握AI开发的核心工具链已经成为从功能测试向AI测试开发、智能化测试转型的核心竞争力。Pyth…...