设计原则
文件上传同时涉及交互、网络、隐私、安全和可访问性。健康上传体验先定义文件目的、限制、API、状态和失败恢复,再选择 react-dropzone、Uppy、FilePond、tus-js-client 或原生 input。
大理论
文件上传是用户把本地或云端私有内容交给系统的边界动作。它看起来像一个控件,实际上包含选择入口、格式限制、文件级队列、网络传输、安全校验、隐私提示、状态公告和最终对象记录。设计上要把 drag/drop 当作快速路径,把可聚焦 browse/input 当作基本路径,把服务端校验当作真实安全边界。
小知识点
- 先写 upload brief:文件目的、允许类型、最大大小、最大数量、是否多文件、是否敏感、上传时机、是否可恢复、最终 remoteId。
accept只是浏览器选择提示,不能证明文件安全。客户端可以提前提示,服务端必须重新校验 MIME、扩展名、大小、数量、权限、病毒扫描和业务规则。- 文件行比总进度更重要:每个文件保留文件名/扩展名、大小、类型、缩略图或图标、状态、进度、取消、删除、重试和错误原因。
- 状态至少覆盖 idle、drag-active、drag-reject、selected、validating、uploading、paused、success、partial-success、error、retrying、cancelled、removed。
- 可访问公告要克制。W3C ARIA25 的上传进度示例用 live region 传达状态,但也提醒 progressbar 的数值变化本身不会自动公告;实际 UI 应公告阶段性状态,不要每 1% 打断读屏。
- 移动端通常没有 drag;需要清晰 browse 按钮、相机/文件入口、安全区域、长文件名换行和虚拟键盘/系统 picker 后的恢复状态。
- 实现资源分层:react-dropzone 解决可定制选择/拖放入口;FilePond 解决较完整的组件体验;Uppy 解决复杂队列、远程来源和插件;tus-js-client 解决可恢复上传协议。
设计判断
如果用户能说明选了哪些文件、哪些被拒绝、为什么失败、还能否取消/重试、上传后文件去了哪里,并且键盘/读屏/移动端都能走完整路径,上传契约成立。若界面只显示一个 drop here 或单个 spinner,就仍然缺少状态证据。
实现建议
建立 UploadFile 与 UploadContract:id、File、name、extension、size、type、previewUrl、status、progress、errorCode、errorMessage、remoteId、uploadEndpoint、validationSource、cancelToken、retryPolicy、scanStatus、privacyNote。前端用原生 file input 或成熟库保留选择路径;缩略图使用 object URL 时要在移除/卸载后 revoke;大文件使用 tus 或分片协议时要设计 resume fingerprint、过期、冲突和后端兼容。QA 覆盖错误类型、超大文件、多文件 partial success、慢网、取消/重试、读屏公告、移动端 picker、长文件名、缩略图失败和组件卸载 cleanup。
反例/风险
accept="image/*" 后就不做服务端校验;拖放是唯一上传路径;所有失败都写 Upload failed;文件名太长挤爆布局或隐藏扩展名;上传中没有取消;失败后丢失文件行导致无法重试;远程云来源通过第三方 Companion 传输却没有隐私说明;对象 URL 和请求在路由切换后泄漏。
案例分析
Carbon File Uploader 把上传拆成默认按钮上传和 drag-and-drop 两个变体,并说明可用于展示上传过程、上传组件不宜在多文件 modal 中使用,还要求错误信息帮助用户恢复。Shopify Drop zone 明确支持拖放或点击浏览,并把 images、documents、CSV imports、media management 和 document collection 作为用例。MDN 的 accept 文档强调它只提供文件类型提示,用户仍可能覆盖选择,因此必须服务端验证。Uppy、FilePond 和 tus-js-client 的官方仓库分别证明完整上传套件、可访问多框架组件和可恢复上传协议是不同层次,agent 不能混为一个“上传库”。
来源链接
Carbon File uploader: https://carbondesignsystem.com/components/file-uploader/usage/ Shopify Drop zone: https://shopify.dev/docs/api/app-home/web-components/forms/drop-zone MDN accept attribute: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/accept W3C ARIA25 upload progress: https://www.w3.org/WAI/WCAG21/Techniques/aria/ARIA25 react-dropzone: https://github.com/react-dropzone/react-dropzone Uppy: https://github.com/transloadit/uppy FilePond: https://github.com/pqina/filepond tus-js-client: https://github.com/tus/tus-js-client
Agent 指令
生成上传界面前必须输出 upload brief、状态机、客户端/服务端校验矩阵、逐文件行、错误恢复、aria-live 策略、隐私说明、API contract 和 cleanup;禁止只画 dropzone 默认态。