golocaldownload
把一个服务器目录,变成可浏览、可检索、可下载的文件站
技术栈
- Go
- Gin
- 内嵌静态资源
- Bootstrap 5
- Docker
概览
golocaldownload 把一个服务器目录变成可浏览、可检索、可下载的文件站。它用 Go + Gin 写成,页面模板、静态资源和配置模板全部通过 //go:embed 内嵌,发布出去就是单个可执行文件 —— 解压即用,不需要 Node、不需要反向代理、不需要数据库。
适合把构建产物、素材包或内部资料挂到一个简单 URL 后面:本机或内网打开即用。
功能
- 目录浏览:面包屑逐级跳转,目录排在文件前面,展示大小与修改时间
- 按类型显示图标:压缩包 / 图片 / 视频 / 音频 / 文档 / 表格 / 代码按扩展名区分,未知扩展名回落通用文档图标
- 全局检索:按文件名忽略大小写子串匹配,可一键定位到文件所在目录,最多返回 500 条
- 文件下载:中文、空格等非 ASCII 文件名按 RFC 5987 编码,浏览器不会存成乱码
- 一键复制地址:文件复制绝对下载地址(浏览器、
wget、下载工具都能直接吃),目录复制定位页面地址 - 主题切换:亮色 / 跟随系统 / 暗色三态,首帧就应用主题,暗色下不闪白屏
- 列表 / 网格双视图:列表看大小与时间,网格按图标认内容;切换不重新请求接口
- 越界防护:列表、检索、下载都限制在下载库之内,
../目录穿越直接拒绝 - 优雅退出:
Ctrl+C或SIGTERM会等待在途下载收尾,不掐断大文件传输
快速开始
需要 Go 1.23 及以上。
# 开发模式直接跑
go run .
# 或编译后运行
go build -o golocaldownload . && ./golocaldownload
启动后会打印版本、配置来源、下载库目录与可访问地址:
golocaldownload dev(debug)
配置来源: config/env.ini
下载库目录: E:\download_lib
本机访问: http://127.0.0.1:9801
局域网访问: http://192.168.1.10:9801
把要对外提供的文件丢进「下载库目录」,刷新页面就能看到。默认监听 9801,下载库是运行目录下的 download_lib/(不存在会自动创建)。
部署方式
| 场景 | 方式 |
|---|---|
| 改代码 / 长期维护 | 本地源码编译(go build) |
| 直接用 | 从 Releases 下载对应平台压缩包,解压即跑 |
| 有 Docker | docker build 本地构建,或用 docker compose up -d |
| 只想拉现成镜像 | Docker Hub 或阿里云 ACR 拉取 |
拉现成镜像最省事:
docker pull tutudev99/golocaldownload:latest
docker run -p 9801:9801 --name golocaldownload \
-v /home/download_lib:/root/download_lib --restart always -d \
tutudev99/golocaldownload:latest
挂载路径的右边必须固定写
/root/download_lib,左边按宿主机填。Windows 上用带盘符的路径(如D:/download_lib),不要写/home/...—— 那会被当成 Docker Desktop 的 WSL2 虚拟机内部路径,数据不在 Windows 上,资源管理器看不到,重置 Docker Desktop 时还会一起丢。
镜像同时覆盖 linux/amd64 与 linux/arm64,ARM 服务器和 Apple Silicon 可直接跑。
配置
配置文件是 INI 格式,来源优先级从高到低:
-config参数 /GLD_CONFIG环境变量指定的文件- 工作目录下的
env.ini - 工作目录下的
config/env.ini - 二进制内嵌的
env.ini.<GLD_ENV>(默认release)
| 配置项 | 默认值 | 说明 |
|---|---|---|
env_mode |
release |
debug / release / test |
download_lib_path |
download_lib |
下载库目录,支持多级相对或绝对路径,自动创建 |
display_lib_path |
空 | 页面上展示的下载库路径;留空时自动识别容器映射的宿主机目录 |
server.http_port |
9801 |
监听端口 |
二进制内嵌了 env.ini.debug / .local / .release / .test 四份模板,源码 clone 下来直接 go build 即可,不需要先把 env.ini.local 改名。
接口
| 方法与路径 | 参数 | 说明 |
|---|---|---|
GET / |
- | 页面 |
GET /api/list |
path(相对下载库的路径,留空为根目录) |
列出目录内容 |
POST /api/search |
表单 keyword |
按文件名检索,最多 500 条 |
GET /api/download |
data(文件路径的 base64url 编码) |
下载文件 |
出错时返回对应状态码与 {"error": "..."}:路径越界 400 / 403,目标不存在 404,目录不可读 403,其他 500。
实现要点
- 所有请求路径都过越界校验:统一走
common.SafeJoin—— 先拒绝含 NUL 的路径,再统一分隔符、清掉首部斜杠,最后用filepath.Rel确认结果没逃出根目录;下载接口还额外校验绝对路径也必须在根目录之内 - 路由常开
Recovery:handler 只返回状态码与错误信息,任何模式下都不会因一次「目录不存在」让进程退出 - 配置访问带默认值且不会 panic:
env_mode非法时回落release,GetInt/GetBool/GetDuration在配置缺失或写错时返回默认值 - 检索用
filepath.WalkDir并限制条数:不跟随符号链接,单条目读不到时跳过,上限 500 条避免撑爆响应体 - 容器里显示宿主机目录:读
/proc/self/mountinfo,按「挂载点是下载库前缀且最长」取记录,用源目录当展示路径 - 产物可复现:
tools/pack用 Go 标准库显式写入 0755 并固定时间戳,同源码在任何平台、用哪个脚本构建,产物与校验和都一致
已知局限
- 没有鉴权 —— 任何能访问端口的人都能浏览与下载全部内容,默认只适合本机或内网
- 没有 HTTPS —— 真正的 TLS 需由前置 Nginx / Caddy 之类的反向代理终结
- 检索是全量遍历 —— 每次请求都
WalkDir一遍,下载库特别大时会偏慢 - 只支持一个下载库根目录,没有上传、删除、重命名等写操作
- 没有断点续传与限速 —— 大文件高并发时容易把带宽打满
- Docker 镜像只覆盖 linux/amd64 与 linux/arm64,其余架构请在宿主机直接跑二进制
许可
最近更新