Send 是一个由管理员上传、通过链接公开分享文件的轻量级应用。后端使用 Go、Gin、GORM 和 SQLite,前端使用 Vue 3、TypeScript、Vite 与 Element Plus。
- 单管理员注册、登录、改密与退出
- 文件扩展名、MIME 类型和大小校验
- 分享密码、有效期和最大下载次数
- 分享链接与二维码
- 可选生成 8 位文件收件码,在公开主页输入后提取文件
- PDF、图片、文本和 JSON 在线预览
- 管理后台搜索、分页、删除文件与调整上传大小
- IP 限流、短期一次性下载凭证和过期文件清理
- Go 1.25 或兼容版本
- Node.js 20+ 与 npm
启动后端:
cd server
go run .后端从 server/config/config.yaml 读取配置,默认监听 8081。首次启动会自动创建 server/data 和 server/uploads。
启动前端开发服务器:
cd web
npm ci
npm run devVite 默认监听 5174,并将 /api 代理到 http://localhost:8081。公开主页用于输入收件码;首次打开 /#/admin/login 时创建管理员,之后 /#/upload 上传页和管理后台都要求登录。
上传时可以选择“生成文件收件码”。收件码由 8 位易读大写字母和数字组成,不区分输入大小写;它只负责定位文件,不会绕过文件访问密码、有效期或下载次数限制。
前端产物与后端二进制需要分别构建。后端使用需要 CGO 的 SQLite 驱动(go-sqlite3),因此构建机器上必须安装 C 编译器:Linux 上使用系统 gcc;Windows 上可使用 MSYS2 的 mingw64(如 C:\msys64\mingw64\bin),构建前把它的目录加入 PATH。
# 1. 构建前端(输出到 web/dist)
cd web
npm ci
npm run build
# 2. 构建后端二进制
cd ../server
CGO_ENABLED=1 go build -o send-server .二进制以 server/ 为工作目录运行——配置文件、数据库和上传目录的路径都相对于工作目录:
cd server
GIN_MODE=release ./send-server- 首次启动会自动创建
server/data与server/uploads,并在启动时清理数据库与磁盘不一致的文件(孤儿文件、中断上传产生的残缺记录)。 GIN_MODE=release让 Gin 进入 release 模式(关闭调试输出);Windows 下可用$env:GIN_MODE="release"。- 服务监听
server/config/config.yaml中配置的端口(默认8081),并直接提供web/dist的静态页面,与 API 同源。
生产环境建议把 Go 服务放在反向代理之后,由代理终结 TLS。此时需要在 server/config/config.yaml 中配置:
trusted_proxies:填入反向代理的 IP(如127.0.0.1、::1或内网网关)。为空时 Gin 不信任任何代理,直接与公网通信的客户端无法伪造X-Forwarded-For绕过限流。allowed_origins:同源部署时留空即可;仅当前端与 API 跨域时才填写前端来源。- 反向代理必须覆盖转发头,不能追加客户端提交的原始值。
nginx 示例(client_max_body_size 必须大于上传大小上限,否则大文件上传会被代理以 413 拒绝):
server {
listen 443 ssl;
server_name send.example.com;
# SSL 证书配置(此处省略)
# 上传大小上限:应不小于管理后台中配置的最大上传大小
client_max_body_size 50m;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr; # 覆盖,而非追加
proxy_set_header X-Forwarded-Proto $scheme;
# 大文件上传需要更长的代理超时
proxy_read_timeout 60s;
proxy_send_timeout 60s;
location / {
proxy_pass http://127.0.0.1:8081;
}
}所有持久化数据都在 server/data(SQLite 数据库)与 server/uploads(上传的文件)两个目录,备份时两者都要保留。迁移到新机器时,将这两个目录连同 server/config/config.yaml 一起拷贝即可。
- 拉取新代码,重新执行上面「构建」的两步;
- 用新二进制重启服务,数据库结构变更由启动时的自动迁移完成;
- 启动时会自动清理孤儿文件,无需手动干预。
镜像在 GitHub Actions(CI)上构建,推到 GitHub Packages(GHCR),服务器 2c2g 只需要 docker pull 和运行,不做任何编译。
- Docker + Docker Compose Plugin(
docker compose version有输出即可) - 2c2g 足够:程序本体很小,前端 + 后端起容器占用约 150–250 MB 内存
-
登录 GHCR(只需权限最小的 PAT,见下):
docker login ghcr.io -u <GitHub用户名> --password-stdin <<< '<PAT>'
PAT 在 GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic),勾选
read:packages即可(只读拉镜像)。 -
创建部署目录并写配置:
mkdir -p send && cd send curl -O https://raw.githubusercontent.com/<你的用户名>/send/main/docker-compose.yml curl -O https://raw.githubusercontent.com/<你的用户名>/send/main/docker-compose.env.example cp docker-compose.env.example .env # 按需编辑 .env,然后:
-
启动:
docker compose up -d
首次会自动从 GHCR 拉取镜像
ghcr.io/<你的用户名>/send:latest。访问http://<服务器IP>:8081。 -
常用命令:
docker compose logs -f # 看日志 docker compose pull && docker compose up -d # 更新到最新镜像
容器内 data/(SQLite 数据库)与 uploads/(上传文件)bind-mount 到宿主机 ./data 与 ./uploads,升级镜像、重建容器都不会丢。备份直接备份这两个目录即可。
生产建议用 Caddy 或 Nginx 把 8081 反代出去并终结 TLS(配置示例见上节)。若反向代理与容器同机,SEND_TRUSTED_PROXIES=127.0.0.1,::1 写进 .env。
想直接用域名 + 自动 HTTPS?把下面这段加进
docker-compose.yml的services:下即可(注意要把send服务旁的ports: - "8081:8081"删掉或改成只监听本机,避免端口给人直连):
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
SEND_TARGET: http://send:8081
volumes:
- ./caddy-data:/data
- ./caddy-config/Caddyfile:/etc/caddy/Caddyfile:ro
depends_on:
- sendCaddyfile(./caddy-config/Caddyfile):
send.example.com {
reverse_proxy send:8081
}
想在本机构建镜像再 docker save/docker load 到服务器也行,但需要一台内存 ≥4G 的机器做编译:
cd 仓库根目录
docker build -t ghcr.io/<你的用户名>/send:latest .
docker save ghcr.io/<你的用户名>/send:latest | gzip > send.tar.gz
# 拷到服务器后:
docker load < send.tar.gz本机没有 Docker 的话,直接用 GitHub Actions 的产物即可,不需要本地构建。
server/config/config.yaml 中的重要配置:
allowed_origins:仅在前后端跨域部署时填写前端来源;同源部署可留空。trusted_proxies:默认不信任任何代理。只有确实位于受控反向代理之后时才填写代理 IP。rate_limit_localhost:为true时 localhost 也参与限流;默认false。
反向代理必须覆盖客户端转发头,不能追加来自公网请求的原始值。例如 nginx:
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;后端测试(需要 C 编译器,见「生产构建与部署」):
cd server
go test ./...前端类型检查与构建:
cd web
npm run buildserver/controller:HTTP 参数处理与文件响应server/service:认证、文件和系统设置业务逻辑server/middleware:认证、CORS、限流、安全头和静态文件server/model:SQLite 数据模型web/src/views:上传、分享、登录和管理页面web/src/api:前端 API 封装