Halo 大文件分片上传插件 (plugin-chunk-upload)
一款专为 Halo 2.x 打造的极简、轻量级浏览器端大文件分片上传与断点续传插件。
当 Halo 站点开启 Cloudflare CDN 代理(小黄云)时,免费版与 Pro 版均受限于单次 HTTP 请求体最大 100MB 的硬性限制(超过即报错 413 Content Too Large)。由于 Halo 原生上传器采用单次请求发送完整文件,即便后端配置了 S3 / OSS 存储策略也无法从控制台直接上传超过 100MB 的附件。
本插件在浏览器端利用 File.slice() 将大文件切分为小分片(如 2MB~50MB),支持多线程并发上传与断点续传,在服务端通过 NIO 零拷贝高速合并后直接调用 Halo 原生 AttachmentService 存入附件库。
- 适用版本:Halo
>= 2.25.0- 构建说明:本插件使用 opencode 与 gemini-4-argon 构建。
- 测试声明:本插件目前仅在个人 Halo 实例的本地存储策略下完成实测验证;使用外部对象存储(如 S3 / OSS)或其他复杂环境的站点建议先测试确认是否可用。
功能特性
- 突破 Cloudflare 100MB 限制:支持在前端自由选择
2 MB、5 MB(默认)、10 MB、20 MB、50 MB分片大小,单次请求远低于网关限制。 - 多线程并发加速:内置并发上传工作池,支持
1 / 2(默认) / 4 / 6 / 8 / 10 / 12线程并发传输。 - 实时网速与丝滑进度:支持字节级进度反馈,实时展示上传速率(
MB/s)、已传大小与预计剩余时间(ETA)。 - 闭环断点续传与自动重试:
- 单个分片遇到网络抖动自动进行指数退避重试(最多 3 次)。
- 支持随时点击「暂停」与「继续上传」。
- 基于文件特征(文件名、总大小、分片大小、最后修改时间、目标存储策略与分组)计算确定性
SHA-256会话 ID;即使意外刷新或关闭网页,重新选择同一文件即可自动跳过已传分片继续上传。
- 无缝对接 Halo 原生附件库:
- 自动读取并同步 Halo 已配置的存储策略(本地存储、S3、阿里云 OSS 等)与附件分组(自动过滤系统隐藏分组)。
- 自动识别文件真实 MIME 类型(视频、音频、图片、文档等均可正常预览与归类)。
- 零数据库污染 & 零拷贝低占用:
- 不创建任何自定义数据库表(Zero Custom Extension)。
- 服务端采用
FileChannel.transferTo内核级零拷贝合并,边合并边释放.part分片,入库后立即清理临时文件,并内置 24 小时过期会话自动清理机制。
安装与使用
1. 安装插件
- 前往 GitHub Releases 下载最新版本的
plugin-chunk-upload-1.0.6.jar。 - 登录 Halo 管理后台 $\rightarrow$ 【插件】 $\rightarrow$ 右上角 【安装】 $\rightarrow$ 上传 JAR 包并启用插件。
- 刷新浏览器页面即可看到入口。
2. 两个使用入口
- 入口一(左侧边栏独立页面):
点击后台左侧导航栏的 【大文件分片上传】,选择存储策略、附件分组、分片大小和并发线程数,拖入大文件即可上传,完成后可一键复制附件永久链接(Permalink)。 - 入口二(文章编辑器附件选择弹窗):
在编写文章或页面时,点击「选择附件」弹窗顶部的 【大文件分片上传】 选项卡,上传完成后会自动勾选该附件,点击右下角「确定」即可直接插入文章。
注意事项
- Halo 存储策略大小与类型限制:
文件合并后通过 Halo 原生AttachmentService入库,仍遵循目标存储策略自身的规则。若使用 Halo 默认的「本地存储」上传超大文件或特殊格式(如.exe、.zip),请先前往 【附件】 $\rightarrow$ 右上角【存储策略】 $\rightarrow$ 编辑【本地存储】,确认「最大单文件大小」设为0(不限制)或足够大,且「文件类型限制」允许对应类型。 - 反向代理(Nginx / 1Panel / Caddy)配置:
请确保源站反向代理的client_max_body_size大于你所选的单次分片大小(例如默认 5MB 分片时,Nginx 配置client_max_body_size 20m;)。 - 服务器临时磁盘空间要求:
分片上传与合并过程在服务器系统临时目录(${java.io.tmpdir}/plugin-chunk-upload)中进行:- 若目标策略为 外部对象存储(S3 / OSS 等),在合并并流式转发至对象存储期间,请确保服务器临时目录剩余可用磁盘空间大于 1 倍 所传大文件的体积(上传完成后临时文件会立即自动清空)。
- 若目标策略为 本地存储 且与系统临时目录位于同一磁盘分区,在合并文件流式写入附件目录的瞬间,请确保剩余可用磁盘空间大于 2 倍 所传大文件的体积(入库完成后临时文件会自动删除,最终仅占 1 倍空间)。
数据与隐私说明
- 临时分片存储边界:上传过程中的临时分片保存在当前 Halo 服务器系统临时目录
${java.io.tmpdir}/plugin-chunk-upload/{uploadId}/下:- 每个分片先写入
.part.uploading并严格校验字节数后原子重命名为.part。 - 合并入库完成或用户点击「取消并清理」时,立即递归删除对应会话目录。
- 中途放弃且未手动清理的会话目录,在超过 24 小时无活跃后会在下次初始化上传或插件启停时自动销毁;卸载插件时会自动清理全部临时分片目录。
- 每个分片先写入
- 无外部通信:本插件所有接口均受 Halo RBAC 权限保护,仅在管理员浏览器与当前 Halo 实例之间传输数据,不包含任何遥测、统计或向第三方服务发送数据的逻辑。
构建说明
本地开发与打包
环境要求:Java 21、Node.js 22+、pnpm 12+
./gradlew clean build
构建产物位于 build/libs/plugin-chunk-upload-*.jar。
- 本插件前后端代码由 opencode 与 gemini-4-argon 编写构建。
许可证
本项目基于 AGPL-3.0 License 开源。