Skip to content

feat(fs): support skipping existing files in copy tasks#9557

Open
okatu-loli wants to merge 1 commit into
AlistGo:mainfrom
okatu-loli:feat/copy-skip-existing
Open

feat(fs): support skipping existing files in copy tasks#9557
okatu-loli wants to merge 1 commit into
AlistGo:mainfrom
okatu-loli:feat/copy-skip-existing

Conversation

@okatu-loli

@okatu-loli okatu-loli commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Closes #9555

问题

跨网盘复制(如 pikpak → 115)任务因关机/网络问题中断后,重新发起复制时 /api/fs/copy 只有 overwrite 一个选项:不勾选则因目标已存在同名直接报错,勾选则所有文件全量重传,已完成的部分被浪费。

方案

POST /api/fs/copy 新增 skip_existing 参数:

  • 目标存在同名且同大小的文件 → 跳过传输,任务直接标记成功(状态显示 skipped: destination file already exists);
  • 同名但大小不一致(上次中断留下的残缺文件)→ 重新复制覆盖;
  • 不传该参数时行为与现状完全一致。

不依赖 MD5/哈希校验——各网盘驱动哈希算法不一致或缺失,跨盘场景大多不可用;同名同大小判定可同时覆盖断点续传与残缺文件重传两个诉求。

实现

  • MoveCopyReq 增加 skip_existing 字段,FsCopy 在该参数开启时放行已存在的目标;
  • 标志通过 context key(仿照 conf.NoTaskKey 模式)传入 fs.Copy,签名不变,既有调用点零改动;
  • CopyTask.SkipExisting 带 json tag 持久化,进程重启恢复任务后标志不丢,目录递归生成子任务时逐层传递;
  • copyFileBetween2Storages 在请求源文件下载链接前探测目标,命中同名同大小即跳过;探测失败(网络等原因)退化为照常复制,最坏多传一次,不会使任务失败;
  • 同存储复制的快速路径对文件做相同跳过判断。

测试

本地两个 Local 存储间实测:

  1. 不带 skip_existingoverwrite=false 复制已存在目录 → 403 file [dir] exists(回归,行为不变);
  2. skip_existing=true 复制目录(目标预置同大小文件、半截文件、缺失文件)→ 同大小文件跳过且内容未被覆盖,半截文件重传为完整内容,缺失文件正常复制;
  3. 同请求重复执行 → 全部跳过,零传输(幂等);
  4. 同存储复制两次 → 第二次直接成功,目标文件 mtime 不变。

配套前端 PR:AlistGo/alist-web(复制对话框新增「跳过已存在文件」选项)。

Add skip_existing option to POST /fs/copy. When enabled, destination
files with the same name and size are skipped instead of failing the
request, so an interrupted cross-storage copy can be resumed without
re-transferring completed files. Files with mismatched sizes (e.g.
truncated by a previous interruption) are re-copied.
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