Skip to content

fix(upload): send a file identity so multipart uploads can resume - #726

Open
thetapilla wants to merge 1 commit into
OpenListTeam:mainfrom
thetapilla:fix/multipart-file-identity
Open

thetapilla wants to merge 1 commit into
OpenListTeam:mainfrom
thetapilla:fix/multipart-file-identity

Conversation

@thetapilla

Copy link
Copy Markdown
Contributor

Summary / 摘要

让分块上传在不勾"尝试秒传"时也能断点续传。

用户可感知的变化:

  • 上传中刷新页面,或关掉页面再打开后重新选择同一文件,会从已接收的分片之后继续,不再从头重传。此前只有勾选秒传、带了文件哈希才能续传

实现要点:

  • init 时发送 X-File-Identity:对文件首尾各 1 MiB 加上文件大小和修改时间计算 SHA-256,用现有依赖 hash-wasm 计算(纯 HTTP 下没有 crypto.subtle)。每个文件最多读取 2 MiB,大文件也不需要等待
  • 每次分块上传都发送,与是否勾选秒传无关;勾选秒传时文件哈希照常发送,服务端会同时比对两者

兼容性说明:不认识 X-File-Identity 的服务端会忽略它,行为与现在相同。

  • This PR has breaking changes.
    / 此 PR 包含破坏性变更。
  • This PR changes public API, config, storage format, or migration behavior.
    / 此 PR 修改了公开 API、配置、存储格式或迁移行为。
  • This PR requires corresponding changes in related repositories.
    / 此 PR 需要关联仓库同步修改。

Related repository PRs / 关联仓库 PR:

Testing / 测试

测试平台:macOS arm64,Node 26 / pnpm 10。

  • go test ./...
    不适用前端仓
  • Manual test / 手动测试:

自动化检查:

  • pnpm test(40/40)、pnpm build 通过
  • pnpm lint(tsc):本 PR 未引入新的类型错误(仓库现存 13 个与本 PR 无关的既有错误,main 上同样存在)
  • 提交经 husky pre-commit 的 prettier 自动格式化
  • 在 Node 中对打包后的真实 multipart.ts 配合模拟服务端跑场景测试(不含在本 PR 中):不勾秒传也发送指纹;同一文件重新选择后指纹不变;文件被修改后指纹改变;原有场景在新旧代码上都通过

浏览器实测:

  • 上传到一半刷新页面,重新选择同一文件:只补传剩余分片,内容一致
  • 上传中途换成同名、同大小、内容不同的文件:不续传,最终是新文件
  • 勾选秒传:先计算哈希再上传,init 同时带指纹和哈希

说明:main 的 pnpm-lock.yaml 缺 katex@0.18.2 条目,pnpm install --frozen-lockfile 会失败(#639 之后 main 的 Rolling Build 也因此失败),本 PR 的 CI 可能在安装依赖一步失败。本 PR 不涉及依赖,本地以 --no-frozen-lockfile 安装后测试,lockfile 未提交。

Checklist / 检查清单

  • I have read CONTRIBUTING.
    / 我已阅读 CONTRIBUTING。
  • I confirm this contribution follows the repository license, contribution policy, and code of conduct.
    / 我确认此贡献符合仓库许可证、贡献规范和行为准则。
  • I have formatted the changed code with gofmt, go fmt, or prettier where applicable.
    / 我已按适用情况使用 gofmt、go fmt 或 prettier 格式化变更代码。
  • I have requested review from relevant maintainers or code owners where applicable.
    / 我已在适用情况下请求相关维护者或代码所有者审查。

AI Disclosure / AI 使用声明

  • This PR includes AI-assisted content.
    / 此 PR 包含 AI 辅助内容。

Tools used / 使用工具:

  • ChatGPT
  • Codex
  • GitHub Copilot
  • Claude
  • Gemini
  • Other (please specify) / 其他(请注明):

Usage scope / 使用范围:

  • Code generation / 代码生成

  • Refactoring / 重构

  • Documentation / 文档

  • Tests / 测试

  • Translation / 翻译

  • Review assistance / 审查辅助

  • I have reviewed and validated all AI-assisted content included in this PR.
    / 我已审核并验证此 PR 中的所有 AI 辅助内容。

  • I have ensured that all AI-assisted commits include Co-Authored-By attribution.
    / 我已确保所有 AI 辅助提交都包含 Co-Authored-By 归属信息。

  • I can reproduce all AI-assisted content included in this PR without any AI tools.
    / 我可以在没有任何 AI 工具的情况下重现此 PR 中包含的所有 AI 辅助内容。

- A receiving multipart session only resumes when the client proves it is
  re-uploading the same file. The uploader only had file hashes for that,
  and computes them only when rapid upload is requested, so by default a
  reload restarted the upload from scratch.
- Send X-File-Identity on init: a SHA-256 over the first and last MiB of
  the file plus its size and modification time, computed with hash-wasm
  (crypto.subtle is unavailable over plain HTTP). It is sent on every
  multipart upload; servers that do not know the header ignore it.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant