很多文件收集工具的首页都很像:一个标题,一段说明,一个选择文件的按钮。真正开始使用以后,问题马上从“能不能上传”变成“谁在什么时候交了什么,文件有没有完整到达,任务结束以后还能不能查到”。
Idrop.in 的仓库把这条链路拆得很清楚:收集任务有截止时间和提交统计,文件支持 5 MB 分片、断点续传和秒传,存储可以在 MinIO、七牛云和本地之间切换,后台还要处理权限、审计和回收站。AI 批阅与实时统计只是其中的附加模块,不能遮住文件本身的生命周期。
分片上传改变了后端的思考方式。一个大文件不再是一次请求,而是一组可以重试、乱序到达、重复提交的片段。服务端要保存上传会话、校验片段编号和内容摘要,并在合并前确认所有片段都在。客户端显示“上传完成”之前,不能只看最后一个请求返回成功;合并、落盘和元数据写入也必须完成。
断点续传也不能只记一个进度条。网络中断以后,客户端需要知道服务端已经收到哪些片段,不能把本地进度当成事实。秒传则要求用文件摘要判断已有对象,但命中以后仍要创建属于当前任务的提交记录,否则同一个文件会出现“文件存在却没有交作业”的错觉。
权限和存储切换是另一组经常被忽略的边界。任务创建者、参与提交的人和后台管理员看到的内容不一样;对象存储的公开地址也不应该直接等同于业务权限。仓库选择运行时切换后端,意味着业务层不能把某个存储厂商的路径格式写死在表里。删除、过期和回收都要经过同一个抽象层,才不会留下无法追踪的孤儿文件。
AI 批阅最好被看成异步工作。提交成功先给出明确回执,评分、雷达图和 SSE 进度随后到达;模型出错时,文件仍然留在任务里,管理员可以重试或手动处理。把模型响应直接放进上传请求,会让一个外部依赖的波动变成整个系统的可用性问题。
这个项目让我更愿意把“表单”看作一条状态机。任务有草稿、开放、截止和归档,提交有上传中、待合并、已完成和失败,文件有存在、回收和删除。状态画清楚以后,前端的页面反而没有那么复杂;状态没有画清楚时,再漂亮的统计图也只是在放大不确定性。
文件收集最终不是上传按钮的竞赛。它要让每一个提交都能被找到、解释、撤回和重新处理。Idrop.in 目前留下的是一套仍在维护的工程骨架,我更愿意记录它的边界,而不是把仓库描述成一个已经覆盖所有场景的答案。
文件平台还要考虑幂等。用户重复点击提交、网络重试或浏览器恢复页面,都可能让同一片段到达两次。服务端需要用任务、文件和片段标识判断这是不是同一次操作,而不能把每个请求都当成新的文件。
权限也不能停在页面。下载地址、管理接口和审计记录要分别考虑有效期、角色与撤销;任务过期后,文件进入回收站并不代表它已经从所有缓存和对象存储中消失。把生命周期写出来,才能在出现误删或重复提交时解释系统做过什么。