阶段 0 — 上传
2.3 阶段 0 — 上传与预处理
客户端
客户端以 multipart POST 将拍摄的图片或 PDF 直接提交至应用程式的上传端点。预处理是伺服器的职责:保持客户端轻量,意味著每个拍摄界面都能受益于相同的标准化流程,而无需将图像处理程式码发布到各个平台。
伺服器端
上传路由在进行任何储存工作前先验证请求:
- 大小限制 — 上传大小依生产环境定义的限制检查。
- 魔术位元组嗅探(magic-byte sniffing) — 伺服器检查缓冲区的开头位元组,确认负载确实是点阵图片(
JPEG、PNG、WEBP、HEIC及其他受支援格式)或 PDF,而不论客户端提供的Content-Type为何。这可拦截以image/*型别夹带的脚本或标记。
被接受的上传接著透过 sharp 进行伺服器端预处理:
- 方向校正 — 基于 EXIF 的自动旋转,使收据在读取阶段前保持正立。
- 压缩 — 图片依为视觉阶段调校的大小与品质设定重新编码。
- 储存 — 处理后的图片写入 Vercel Blob 物件储存,当 Blob 储存不可用时有资料库备援路径。储存的图片依保留策略排程删除。
回应回传 receipt_id 与储存的图片引用。客户端接著呼叫 POST /api/receipt/analyze 进入阶段 1。
去重
在任何昂贵作业开始前,系统会先执行精确档案杂凑检查:上传位元组的 SHA-256 与先前储存的收据比对。感知相似度检查刻意延后至内容提取之后,以便与内容杂凑交叉验证;过早执行视觉比对会把运算花在精确检查已能解决的上传上。
两种重复情况都会以重复错误拒绝上传:
- 同使用者重复 — 系统告知使用者已上传过这张收据。这可防止意外重复上传与重复奖励尝试。
- 跨使用者碰撞 — 系统告知使用者这张收据已由另一个帐号上传。这是反耕作(anti-farming)防御的一部分。
确切的相似度讯号在生产环境中调校,并由内部营运层管理。