You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring MVC Web应用中集成文档扫描器?求免费可行方案

免费Web文档扫描方案适配Spring MVC

我完全懂你的困扰——传统的TWAIN Applet早就不符合现代Web标准了,不仅HTML5弃用了它,64位系统还不支持,付费方案又超出预算。下面给你几个实用的免费方案,完美适配你的Spring MVC项目:

1. 用开源社区版Web TWAIN SDK

Dynamic Web TWAIN有个免费社区版,足够满足基础扫描需求,不需要Applet,直接用JS就能调用本地扫描设备,而且兼容64位系统和主流浏览器(Chrome、Firefox、Edge这些都支持)。

前端集成示例

先引入SDK的JS文件,然后写扫描逻辑:

// 初始化扫描对象
Dynamsoft.DWT.CreateDWTObjectEx({ "WebTwainId": "scanner" }, function(obj) {
  // 选择扫描设备
  obj.SelectSource(function() {
    obj.OpenSource();
    // 开始扫描,扫描后自动上传到后端
    obj.AcquireImage({
      OnPostTransfer: function() {
        // 把扫描图转成Blob
        obj.ConvertToBlob(Dynamsoft.DWT.EnumDWT_ImageType.IT_PNG, function(blob) {
          let formData = new FormData();
          formData.append("scanFile", blob, "scanned-document.png");
          // 调用Spring MVC上传接口
          fetch("/api/upload-scanned-file", { 
            method: "POST", 
            body: formData 
          }).then(res => res.text()).then(msg => {
            console.log(msg);
          });
        });
      }
    });
  });
});

Spring MVC后端接口

写个接收文件的接口,处理上传后的存储或业务逻辑:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

@RestController
public class ScanUploadController {

    @PostMapping("/api/upload-scanned-file")
    public ResponseEntity<String> uploadScannedFile(@RequestParam("scanFile") MultipartFile file) {
        if (file.isEmpty()) {
            return ResponseEntity.badRequest().body("上传文件不能为空");
        }
        try {
            // 存储到服务器指定目录
            Files.write(Paths.get("scanned-documents/" + file.getOriginalFilename()), file.getBytes());
            return ResponseEntity.ok("文件上传成功,已保存至服务器");
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败");
        }
    }
}

2. 纯HTML5原生方案(依赖现代设备)

现在不少新款扫描仪支持被浏览器的MediaDevices API识别为图像捕获设备,你可以直接用原生JS调用设备流,捕获帧作为扫描文件,完全不需要第三方库,免费又轻量。

前端核心代码

async function initScanner() {
    try {
        // 获取所有媒体设备,筛选出扫描仪
        const devices = await navigator.mediaDevices.enumerateDevices();
        const scannerDevice = devices.find(device => device.kind === 'videoinput' && device.label.includes('Scanner'));
        
        if (!scannerDevice) {
            alert("未检测到兼容的扫描设备");
            return;
        }

        // 请求设备流
        const stream = await navigator.mediaDevices.getUserMedia({
            video: { 
                deviceId: { exact: scannerDevice.deviceId },
                width: { ideal: 2000 }, // 按需设置分辨率
                height: { ideal: 1600 }
            }
        });

        const videoElement = document.getElementById('scanner-preview');
        videoElement.srcObject = stream;

        // 捕获按钮点击事件
        document.getElementById('capture-btn').addEventListener('click', () => {
            const canvas = document.createElement('canvas');
            canvas.width = videoElement.videoWidth;
            canvas.height = videoElement.videoHeight;
            // 绘制视频帧到画布
            canvas.getContext('2d').drawImage(videoElement, 0, 0);
            // 转成Blob上传
            canvas.toBlob(blob => {
                let formData = new FormData();
                formData.append("scanFile", blob, "scanned-image.jpg");
                fetch("/api/upload-scanned-file", { 
                    method: "POST", 
                    body: formData 
                });
            }, 'image/jpeg', 0.9);
        });
    } catch (err) {
        console.error("扫描初始化失败:", err);
        alert("请确保已授权浏览器访问设备,且扫描仪驱动正常");
    }
}

⚠️ 注意:这个方案只支持支持WebRTC的扫描仪,老设备可能不兼容,但胜在零依赖,完全免费。

3. 本地辅助程序+Spring MVC接口(兼容老设备)

如果你的用户用的是老款扫描仪,上面的Web方案都不兼容,可以写个轻量的本地桌面程序,通过HTTP接口和前端、Spring MVC后端交互。

比如用Python的PyTWAIN库写个本地扫描服务:

from twain import SourceManager
from flask import Flask, send_file
import os

app = Flask(__name__)
SCAN_DIR = './scanned_files'
os.makedirs(SCAN_DIR, exist_ok=True)

@app.route('/trigger-scan')
def trigger_scan():
    try:
        sm = SourceManager(0)
        source = sm.OpenSource()
        source.RequestAcquire(0, 1) # 触发扫描
        image = source.GetImage()
        file_path = os.path.join(SCAN_DIR, 'scanned_doc.png')
        image.Save(file_path)
        # 返回扫描文件,前端可以拿到后上传到Spring MVC
        return send_file(file_path, mimetype='image/png')
    except Exception as e:
        return str(e), 500

if __name__ == '__main__':
    app.run(port=8081, debug=True)

前端可以通过fetch('http://localhost:8081/trigger-scan')获取扫描文件,再上传到你的Spring MVC后端接口。

最后要提醒的是:所有方案都需要用户本地安装好扫描仪的官方驱动,Web方案还需要用户在浏览器中授权访问设备的权限。

内容的提问来源于stack exchange,提问作者new coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:54:37