系统概述

v2.0 · 自动纠偏 · 阿里云

📋 系统概述

本系统实现 良田(ELoam)高拍仪 的Web拍照与自动上传功能。通过浏览器即可操作高拍仪拍照,照片自动上传到配置的阿里云服务器。


核心能力:

  • 通过WebSocket调用良田SDK(eloamwebservice)控制高拍仪
  • 支持 自动纠偏(SetDeskew) — 拍照后自动检测试卷/文档边界并拉正
  • 照片上传到阿里云服务器,文件名包含操作人姓名
  • 所有服务器连接配置(地址、端口、用户名、密码)可通过Web界面动态修改


适用场景: 试卷扫描、文档归档、证件拍照上传等需要高拍仪配合云存储的场景。

✅ 验证结果

功能状态说明
SDK WebSocket连接✓ 通过eloamwebservice 127.0.0.1:9000
设备初始化 InitDevs✓ 通过自动处理 ret=2 (Init again) 重试
打开摄像头 OpenCamera✓ 通过需 datacallback:true
拍照 ScanImage✓ 通过base64模式,约400KB/张
自动纠偏 SetDeskew✓ 通过ret=0,拍照前设置
上传至阿里云✓ 通过FTP协议连接阿里云服务器
HTTP服务端口3001✓ 通过Express + 静态文件

🏗️ 系统架构图

🌐 浏览器
index.html
HTTP (fetch)
🖥️ Node.js 服务器
server.js :3001
WebSocket
📷 eloamwebservice
:9000
🔌 USB 高拍仪
S1280AF
📤 上传通道
FTP协议
☁️ 阿里云服务器
公网IP

浏览器 → Node.js服务器 → eloamwebservice → 高拍仪(拍照),Node.js → 阿里云服务器(上传)

🔧 技术栈

后端

  • Node.js v22
  • Express 4.18
  • ws 8.21 (WebSocket客户端)
  • basic-ftp 5.0
  • multer (文件上传)

前端

  • 原生HTML + CSS + JavaScript
  • 无框架依赖
  • Fetch API
  • 响应式设计

外部依赖

  • eloamwebservice.exe (SDK服务)
  • Windows USB驱动
  • 阿里云服务器 (FTP服务端)

硬件

  • 良田高拍仪 S1280AF
  • 3264×2448 最大分辨率
  • USB 连接

🔌 API 接口文档

所有接口返回 JSON 格式。基础地址:http://localhost:3001

方法路径说明关键参数
GET/capture拍照deskew=1 启用自动纠偏
POST/upload上传Base64图片到阿里云image, name, filename
POST/upload-file上传文件到阿里云file (multipart)
GET/config获取阿里云连接配置-
POST/config修改阿里云连接配置host, port, user, password
GET/test-ftp测试阿里云连接-
GET/health健康检查-

📸 GET /capture 拍照

调用高拍仪SDK完成拍照,返回Base64格式JPEG图片。

GET http://localhost:3001/capture?deskew=1

参数:

参数类型默认说明
deskewstring01true 启用自动纠偏

响应示例:

{
  "success": true,
  "data": "data:image/jpeg;base64,/9j/4AAQ...",
  "size": 243461,
  "deskew": true,
  "time": "2026-06-11T10:52:34.959Z"
}

📤 POST /upload 上传图片

将Base64图片数据上传到阿里云服务器(通过FTP协议)。文件名自动包含操作人姓名。

POST http://localhost:3001/upload
Content-Type: application/json

{
  "image": "data:image/jpeg;base64,/9j/4AAQ...",
  "name": "张三",
  "filename": "张三_1718000000000.jpg"
}

响应示例:

{
  "success": true,
  "message": "上传成功",
  "path": "张三_1718000000000.jpg",
  "size": 243461,
  "name": "张三",
          "url": "ftp://阿里云地址/张三_1718000000000.jpg"
}

📁 项目文件结构

所有源码在 C:\良田高拍仪v8.1\ftp-upload\ 目录下:

文件大小说明
server.js ~11KB 主服务程序 — Express HTTP服务 + WebSocket相机控制 + 阿里云上传,含SetDeskew自动纠偏
index.html ~13KB 用户界面 — 阿里云配置、拍照控制、图片预览、上传操作、自动纠偏开关
package.json <1KB Node.js依赖声明(express, ws, basic-ftp, multer)
ftp_config.json <1KB 运行时生成的阿里云连接配置持久化文件
test-upload.js ~2KB 上传功能测试脚本
README.md ~3KB 说明文档
docs.html 本页 交互式技术文档
node_modules/ 自动生成 npm依赖包(无需手动修改)

📄 server.js 核心模块

server.js 包含以下功能模块:

模块行数功能
阿里云配置管理14-43加载/保存 ftp_config.json
上传函数66-92uploadToFtp() — 通过FTP协议上传文件到阿里云
相机拍照函数94-202captureFromCamera() — WebSocket控制SDK完成拍照
拍照接口204-218GET /capture?deskew=0|1
配置接口220-241GET|POST /config
上传接口243-283POST /uploadPOST /upload-file
测试接口285-314GET /test-ftpGET /health
文件查找接口316-339GET /find-capture(备用)

📄 index.html 界面布局

区域功能
阿里云服务器配置主机地址、端口、用户名、密码输入 + 保存/测试按钮
操作人信息姓名输入(文件名中使用),保存到localStorage
服务状态显示服务器健康状态指示灯
拍照控制拍照按钮 + 自动上传开关 + 自动纠偏开关
图片预览拍照后显示图片,上传/清除按钮
操作日志实时显示所有操作记录
进度覆盖层上传时显示进度条

🚀 安装与启动

前置条件: 已安装 eloamwebservice(良田SDK服务),摄像头已通过USB连接。

📦 安装依赖

cd C:\良田高拍仪v8.1\ftp-upload
npm install

会自动安装 expresswsbasic-ftpmulter

▶️ 启动服务

方式一:前台运行(推荐)

cd C:\良田高拍仪v8.1\ftp-upload
npm start

看到启动横幅后打开浏览器访问 http://localhost:3001


方式二:后台运行(隐藏窗口)

Start-Process -FilePath "node" -ArgumentList "server.js" -WorkingDirectory "C:\良田高拍仪v8.1\ftp-upload" -WindowStyle Hidden

📋 启动日志说明

已加载保存的FTP配置

╔══════════════════════════════════════════════════════════╗
║          高拍仪上传服务已启动(阿里云)                    ║
╠══════════════════════════════════════════════════════════╣
║  服务地址: http://localhost:3001
║  阿里云服务器: 已配置
║  监控文件夹: C:\良田高拍仪v8.1\Scans
╠══════════════════════════════════════════════════════════╣
║  [文件监控]  (启动时自动运行)                              ║
║  POST /watcher/stop   - 停止监控                          ║
║  GET|POST /watcher/config - 监控配置                      ║
║  GET  /watcher/history - 上传历史记录                      ║
╠══════════════════════════════════════════════════════════╣
║  [相机控制]                                               ║
║  GET  /capture       - 拍照 (调用高拍仪SDK)               ║
║  POST /upload       - Base64图片上传 (支持name参数)       ║
╠══════════════════════════════════════════════════════════╣
║  [系统配置]                                               ║
║  GET|POST /config   - 阿里云连接配置                      ║
║  GET  /test-ftp     - 测试阿里云连接                      ║
║  GET  /health       - 健康检查                            ║
╚══════════════════════════════════════════════════════════╝

[2026-06-11T10:51:28.238Z] 服务已就绪,文件监控已自动启动

🔍 验证服务

# 健康检查
curl http://localhost:3001/health
# 返回: {"status":"ok","time":"2026-06-11T10:00:00.000Z"}

# 测试阿里云连接
curl http://localhost:3001/test-ftp
# 返回: {"success":true,"message":"连接成功","config":{...}}

📖 使用指南

打开浏览器访问 http://localhost:3001,界面包含以下操作区域:

① 配置阿里云服务器

填写阿里云服务器地址、FTP端口、用户名、密码,点击 "保存阿里云配置"。配置会自动保存到 ftp_config.json,下次启动自动加载。

点击 "测试连接" 验证阿里云是否可达。

② 输入操作人姓名

填写姓名后点击保存。上传到阿里云的文件名会自动包含该姓名,例如 张三_1718000000000.jpg

③ 拍照

点击 "拍照" 按钮,服务端自动完成以下流程:

连接SDK → 初始化设备 → 设置纠偏(可选) → 打开摄像头 → 等待3秒 → 拍照 → 返回图片

整个过程约 5~6秒。拍照完成后图片自动显示在预览区域。

勾选 "启用自动纠偏" 后,SDK会自动检测试卷/文档边界并拉正。

④ 上传到阿里云

拍照后手动点击 "上传到阿里云" 上传。

或勾选 "拍照后自动上传到阿里云",拍照完成后自动上传。

⑤ 查看日志

底部日志区域实时显示所有操作记录,包括SDK通信状态和上传结果。

🔄 SDK交互流程图

每次拍照(GET /capture)触发以下完整WebSocket交互序列:

📡 WebSocket消息序列

InitDevs
ret=0 / ret=2
(若ret=2) DeinitDevs → InitDevs
SetDeskew
ret=0
(仅deskew=1时)
OpenCamera
ret=0
等待3秒
摄像头就绪
ScanImage
ret=0, base64
CloseCamera
DeinitDevs

📝 关键代码:captureFromCamera()

function captureFromCamera(options = {}) {
  return new Promise((resolve, reject) => {
    // 1. 连接WebSocket到 127.0.0.1:9000
    // 2. InitDevs → 若 ret=2 则 DeinitDevs 后重试
    // 3. (可选) SetDeskew(isdeskew:1) → ret=0
    // 4. OpenCamera(device:0, resolution:0, datacallback:true)
    // 5. 等待 3 秒
    // 6. ScanImage(imagepath:'', colorize:0, type:true, quality:80)
    // 7. 返回 base64 JPEG 数据
    // 8. 清理: CloseCamera → DeinitDevs → ws.close()
  });
}

📋 SDK消息示例

发送: {"function":"InitDevs"}
收到: {"function":"InitDevs","ret":2,"value":"Init again"}
发送: {"function":"DeinitDevs"}
收到: {"function":"DeinitDevs","ret":0,"value":"success"}
发送: {"function":"InitDevs"}
收到: {"function":"InitDevs","ret":0,"value":"success"}
发送: {"function":"SetDeskew","isdeskew":1}
收到: {"function":"SetDeskew","ret":0,"value":"success"}
发送: {"function":"OpenCamera","device":0,"resolution":0,"datacallback":true}
收到: {"function":"OpenCamera","ret":0,"value":"success"}
# 等待 3 秒
发送: {"function":"ScanImage","imagepath":"","colorize":0,"type":true,"quality":80}
收到: {"function":"ScanImage","ret":0,"value":"/9j/4AAQSkZJRgABAQEA... (base64数据)"}

📤 上传至阿里云流程

使用 basic-ftp 库通过FTP协议上传到阿里云服务器。阿里云上需开启FTP服务(如 vsftpd 或 Windows FTP服务端)。

📝 上传流程

浏览器 → POST /upload {image, name, filename}
   → 服务端解码base64为Buffer
   → 构建文件名: {姓名}_{时间戳}.jpg
   → 连接阿里云FTP: client.access({host, port, user, password})
   → 上传: client.uploadFrom(stream, filename)
   → 返回: {success, path, size, url}

🔧 阿里云连接配置

通过Web界面配置阿里云FTP连接信息,保存到 ftp_config.json

{
  "host": "阿里云公网IP",
  "port": 12121,
  "user": "ftp用户名",
  "password": "ftp密码"
}

⚠ 密码明文存储在本地文件,建议阿里云上为每个学校创建独立FTP账号以控制权限。

📄 文件名规则

场景文件名示例
有操作人姓名张三_1718000000000.jpg
无操作人姓名eloam_1718000000000.jpg
自定义文件名以请求中 filename 为准

❓ 常见问题

🔴 打开摄像头失败 ret=-3

原因: 摄像头被其他进程独占(如 EloamCamera.exe)。

解决:

# 查找并杀掉占用摄像头的进程
taskkill /F /IM EloamCamera.exe
# 重启eloamwebservice
taskkill /F /IM eloamwebservice.exe
# 重新启动服务

🔴 InitDevs 返回 ret=2 "Init again"

说明: SDK已经初始化,需要先反初始化再重新初始化。

处理: 系统会自动发送 DeinitDevs 后重试 InitDevs

🔴 拍照返回 ret=-2

原因: ScanImage 参数不兼容。base64 模式(imagepath:'')在某些SDK版本中不可用。

解决: 已经调通 base64 模式,如果再次出现可切换为文件路径模式(指定 imagepath 为文件路径后再读取)。

🔴 无法连接 eloamwebservice

原因: SDK服务未启动或端口9000被占用。

解决:

# 检查服务是否运行
netstat -ano | findstr ":9000"
# 启动服务(以管理员身份)
"C:\Program Files (x86)\eloamwebservice\bin\eloamwebservice.exe"

🔴 无法连接到阿里云服务器

  • 检查阿里云服务器是否运行中、FTP服务是否已启动
  • 在Web界面重新配置正确的地址/端口/用户名/密码
  • 检查阿里云安全组是否放行了FTP端口
  • 使用 GET /test-ftp 测试连接

🔴 端口3001被占用

# 查看哪个进程占用3001
netstat -ano | findstr ":3001"
# 杀掉进程
taskkill /F /PID <进程ID>

⚠️ 文件监控模式注意事项

① 多人共用电脑需独立文件夹

多位老师共用一台电脑时(各自 Windows 账号登录),监控文件夹必须按用户隔离:

C:\Users\教师A\Pictures\高拍仪扫描\
C:\Users\教师B\Pictures\高拍仪扫描\

每个老师各自启动 start.bat,各自监控自己的目录。

② EloamCamera 保存路径需手动设置

打开 EloamCamera.exe → 设置/配置 → 保存路径 → 改成上述监控文件夹。
否则图片保存到默认位置,不会被检测到上传。

⚠️ 安全风险与注意事项

① 阿里云密码明文存储风险

FTP密码保存在本机 ftp_config.json 文件中,为明文形式。任何能使用这台电脑的人都可以用记事本打开查看密码。
建议:阿里云上为每个学校创建独立的FTP账号,密码泄露时只需吊销单个账号。

② 文件监控无上传失败提示

文件监控模式下,如果上传失败(如网络断开、阿里云FTP服务宕机),用户不会收到任何弹窗或通知。失败记录仅在网页历史记录中可查,但用户可能不会主动去查看。
建议:定期检查上传历史记录,或观察文件是否堆积在监控文件夹中未被删除。

③ 重复启动风险

多次双击 start.bat 会启动多个 Node.js 进程,导致端口3001冲突或重复监控。
建议:启动前先运行 stop.bat 确保旧进程已终止。

④ 上传后误删源文件

如果勾选了"上传后删除源文件",但上传实际是失败的(如FTP返回假成功),源文件会丢失。
建议:谨慎使用"上传后删除"选项,建议先观察一段时间确认上传可靠后再启用。

📊 方案对比 | ☁️ 中转概述 | 🔧 中转技术方案 | ← 主页