Skip to content

feat(drivers): add huggingface cloud storage driver - #2799

Open
WUHINS wants to merge 4 commits into
OpenListTeam:mainfrom
WUHINS:main
Open

feat(drivers): add huggingface cloud storage driver#2799
WUHINS wants to merge 4 commits into
OpenListTeam:mainfrom
WUHINS:main

Conversation

@WUHINS

@WUHINS WUHINS commented Jul 16, 2026

Copy link
Copy Markdown

Summary / 摘要

实现了 HuggingFace 仓库作为 OpenList 存储驱动的完整功能。

用户可感知的变化

  • 新增 HuggingFace 驱动类型,支持模型(model) / 数据集(dataset) / 空间(space) 三种仓库
  • 支持配置项:repo_id(必填)、api_tokenref(分支/标签/commit SHA,默认 main)、repo_type(默认 model)、hf_proxy(代理地址)
  • 文件上传:<5MB 走 base64 NDJSON 内联提交,≥5MB 自动切换到 HuggingFace LFS(S3 presigned URL 直传)
  • 支持目录创建(.gitkeep 方式)、文件/目录删除、文件列表、下载直链生成

重要实现变化

  • 新增 5 个文件:drivers/huggingface/driver.go(核心逻辑)、meta.go(驱动元数据)、types.go(API 类型)、util.go(工具函数),以及在 drivers/all.go 注册

  • LFS 上传流程:saveStream 写临时文件 + SHA256 → preupload 检测 → LFS batch API 获取 S3 presigned URL → PUT 直传 S3(支持 fallback 到 POST)→ verify(可选)→ NDJSON commit 提交 lfsFile 引用

  • 小型文件流式提交:io.Pipe + base64 编码 + NDJSON 内嵌,避免写临时文件

  • 自定义 HTTP 客户端:s3Client() 单例共享连接池(5 分钟 ResponseHeaderTimeout),hfClient() 独立客户端(DisableKeepAlives)用于 HF API

  • context.WithoutCancel 保护 S3 上传 body 不被任务取消中断

  • 过滤未签名的 x-amz-* 头部,避免 S3 403(X-Amz-SignedHeaders=host)

  • saveStream 增加 fi.Size() != stream.GetSize() 校验,提前捕获数据不完整

  • 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:

  • OpenList-Frontend:
  • OpenList-Docs:

Related Issues / 关联 Issue

Testing / 测试

  • go build -o OpenList.exe . — 编译通过,生成 ~124MB 可执行文件
  • Manual test / 手动测试:
    • 目标驱动上下传(上传小文件、大文件 LFS 自动切换)
    • 文件复制、目录创建、删除操作
    • 代理配置(hf_proxy)验证
    • 使用 Go 1.23+ 构建,全量编译无报错

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.
    / 我已按适用情况使用 gofmtgo fmtprettier 格式化变更代码。
  • 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) / 其他(请注明): opencode (deepseek-v4-flash-free)

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 辅助内容。


代码实现思路和驱动编写方向由开发者指导,针对 HF 官方 API,初次尝试编写 OpenList 驱动。如有缺陷请指出。


如果需要我调整措辞或增减内容,直接说。

WUHINS added 2 commits July 16, 2026 23:33
实现了HuggingFace仓库作为存储驱动的完整功能,支持模型/数据集/空间三种仓库类型,支持代理配置、LFS大文件上传、目录创建和删除等操作,同时在drivers/all.go中注册该驱动。
重新导入三个编写过程中因意外丢失的存储驱动

@jyxjjj jyxjjj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

临时文件不要提交

清理仓库中不再需要的.tmp/CloudPaste和.tmp/OpenList-Frontend临时子模块
@WUHINS

WUHINS commented Jul 16, 2026

Copy link
Copy Markdown
Author

临时文件不要提交

已改正,感谢提醒

@zjhcx

zjhcx commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

HF仓库已经支持S3访问了,数据集还不支持

@WUHINS

WUHINS commented Jul 17, 2026

Copy link
Copy Markdown
Author

HF仓库已经支持S3访问了,数据集还不支持

所以主要是支持模型和数据集,只是对接API的话顺手做全可能更好,毕竟小白不一定知道HF支持S3,S3配置也有点难度。

@xrgzs xrgzs changed the title feat(huggingface): add huggingface cloud storage driver feat(drivers): add huggingface cloud storage driver Jul 17, 2026
@xrgzs xrgzs added enhancement Module: Driver Driver-Related Issue/PR labels Jul 17, 2026
@WUHINS

WUHINS commented Jul 17, 2026

Copy link
Copy Markdown
Author

HF仓库已经支持S3访问了,数据集还不支持

我看官方说法是桶支持,但标准的模型、数据集几乎不支持
且官方似乎没有明确说明桶是否免费。

@zjhcx

zjhcx commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

HF仓库已经支持S3访问了,数据集还不支持

我看官方说法是桶支持,但标准的模型、数据集几乎不支持 且官方似乎没有明确说明桶是否免费。

确实,不过我试了一下,桶目前是和数据集和模型共享存储空间的

@WUHINS

WUHINS commented Jul 27, 2026

Copy link
Copy Markdown
Author

HF仓库已经支持S3访问了,数据集还不支持

我看官方说法是桶支持,但标准的模型、数据集几乎不支持 且官方似乎没有明确说明桶是否免费。

确实,不过我试了一下,桶目前是和数据集和模型共享存储空间的

当这吃的是私人仓库空间好像,我打算是白嫖公共空间用来挂载AI数据

@xrgzs xrgzs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WUHINS

  1. go fmt 跑一下,代码格式有问题
  2. 自建请求客户端,无适配OpenList Conf代理配置逻辑,建议先检查一下是否真的需要,否则直接用base中的即可。(让AI看一遍internal/net)
  3. 文档弄一下:https://github.com/OpenListTeam/OpenList-Docs

Comment thread drivers/huggingface/driver.go Outdated
return d.lfsUploadAndCommit(ctx, tmp, filePath, fileName, sha256Hex, size, up)
}
return d.streamCommit(ctx, tmp, filePath, fileName, size, up)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

全量落盘,未使用框架的流式缓存工具 internal/stream.CacheFullAndHash,建议整改

Comment on lines +26 to +37
// hfClient is a dedicated HTTP client for HF API requests,
// separate from base.HttpClient to avoid keep-alive connection reuse issues.
func hfClient() *http.Client {
return &http.Client{
Timeout: 30 * time.Minute,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: false},
DisableKeepAlives: true,
MaxIdleConns: 0,
},
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个是不是不会走配置文件中的代理?

Comment on lines +297 to +321
// s3Client returns a shared HTTP client for S3 LFS uploads.
func s3Client() *http.Client {
s3HTTPClientOnce.Do(func() {
s3HTTPClient = &http.Client{
Timeout: 30 * time.Minute,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: false,
MinVersion: tls.VersionTLS12,
},
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
ForceAttemptHTTP2: false,
MaxIdleConns: 2,
MaxIdleConnsPerHost: 2,
IdleConnTimeout: 90 * time.Second,
ResponseHeaderTimeout: 5 * time.Minute,
ExpectContinueTimeout: 5 * time.Second,
},
}
})
return s3HTTPClient
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个是不是不会走配置文件中的代理?

@WUHINS

WUHINS commented Aug 1, 2026

Copy link
Copy Markdown
Author

@WUHINS

  1. go fmt 跑一下,代码格式有问题
  2. 自建请求客户端,无适配OpenList Conf代理配置逻辑,建议先检查一下是否真的需要,否则直接用base中的即可。(让AI看一遍internal/net)
  3. 文档弄一下:https://github.com/OpenListTeam/OpenList-Docs

文档已提交 OpenListTeam/OpenList-Docs#351

hfClient() 与 s3Client() 的自定义 Transport 现在都会调用 netutil.SetProxyIfConfigured(transport)(internal/net/util.go 中定义),读取 conf.Conf.ProxyAddress 并设置 transport.Proxy,因此两个客户端都会遵循 OpenList Conf 中配置的代理。

关于"是否真的需要自定义客户端,还是直接复用 base 中的":我们排查了 internal/net 和 drivers/base/client.go,结论是这两个客户端有必要保留,理由如下:

base.HttpClient(即 net.NewHttpClient())默认带 DisableKeepAlives=false、开启 HTTP/2,且无 S3 上传所需的连接参数定制;
hfClient 需要 DisableKeepAlives: true 规避 HF Commit API 的 keep-alive 连接复用问题(这是当初拆出自定义 client 的原因);
s3Client 需要 ForceAttemptHTTP2: false、MaxIdleConns、Dialer 超时等针对 HF LFS 后端 S3 上传的调优,base.HttpClient 无法覆盖这些场景
因此保留自建客户端是合理的,现在也已补上代理适配。

@WUHINS
WUHINS requested review from jyxjjj and xrgzs August 1, 2026 13:28
@WUHINS

WUHINS commented Aug 1, 2026

Copy link
Copy Markdown
Author

感谢 review,三条意见都已在提交 752f237 中处理完毕:

  1. 全量落盘,未使用框架的流式缓存工具 —— 已修复。Put() 现在使用 stream.CacheFullAndHash(file, &up, utils.SHA256),返回缓存文件及 SHA-256 十六进制哈希。原先的 saveStream() 辅助函数、os.CreateTemp、os.Remove、手动 sha256.New() 逻辑均已移除。streamCommit、lfsUploadAndCommit、streamUpload、streamUploadPost、doCommitLFS 现在统一接收 model.File 缓存,通过框架的混合流式缓存读取,不再将整个临时文件写入磁盘。

  2. 自定义 HTTP client 未适配 OpenList Conf 代理配置 —— 已修复。hfClient() 与 s3Client() 现在都调用 netutil.SetProxyIfConfigured(transport)(定义于 internal/net/util.go),读取 conf.Conf.ProxyAddress 并设置 transport.Proxy,两个客户端都会遵循 OpenList 中配置的代理。

关于"是否真的需要自定义客户端、能否直接复用 base.HttpClient":排查 internal/net 与 drivers/base/client.go 后,结论是保留自定义客户端是合理的:

base.HttpClient(即 net.NewHttpClient())不提供 DisableKeepAlives、禁用 HTTP/2、以及面向 S3 上传的连接参数定制;
hfClient 需要 DisableKeepAlives: true 规避 HF Commit API 的 keep-alive 连接复用问题(当初拆分独立 client 的原因);
s3Client 需要 ForceAttemptHTTP2: false、MaxIdleConns 以及针对 HF LFS 后端(S3)上传定制的 Dialer 超时,base.HttpClient 无法覆盖。
因此保留自建客户端,并已补充代理适配。

  1. gofmt 代码格式 —— 已修复。gofmt -l drivers/huggingface/ 现在无任何输出;types.go 的结构体字段对齐、util.go 的 import 顺序均已修正。

  2. 文档 —— 已在 OpenList-Docs 仓库新增 pages/guide/drivers/huggingface.md,中英双语覆盖 仓库 ID、API Token、引用(Ref)、仓库类型、HF Proxy、根目录路径、上传说明 及 默认下载方式流程图

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Module: Driver Driver-Related Issue/PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants