# tmp-upload
一个自托管的临时文件分享服务。上传文件后获得一个下载链接,**24 小时后自动删除**。
* Single binary,no runtime dependencies
* Built-in web UI (zero external assets)
* 10 GB default quota (configurable)
* Daily audit log (optional)
---
## 快速开始
```bash
go build -o server .
./server
# → 浏览器打开 http://localhost:8080
```
```bash
# 命令行上传
curl -F "file=@report.pdf" http://localhost:8080/upload
# → {"filename":"report.pdf","url":"/download/report-2026-08-27-abc123.pdf","expires_at":"..."}
```
---
## 配置(命令行 flag)
```text
-dir ./data/uploads 上传文件保存目录
-listen :8080 HTTP 监听地址
-ttl 24h 文件过期 TTL
-scan 1h 清理扫描间隔
-quota 10737418240 总目录配额(字节,默认 10 GB;0 = 不限)
-audit-dir ./data/audit 审计日志目录(每天一个 YYYY-MM-DD.log 文件;空字符串禁用)
```
示例:把 TTL 改成 1 小时、配额 1 GB:
```bash
./server -ttl 1h -quota 1073741824
```
---
## HTTP API
| Method | Path | 说明 |
|--------|----------------------------|--------------------------------------------|
| GET | `/` | Web UI(单 HTML 响应,内联 CSS + JS) |
| POST | `/upload` | 上传文件(`multipart/form-data`,字段名 `file`) |
| GET | `/files` | 列出当前未过期文件 |
| GET | `/download/:filename` | 下载文件 |
| POST | `/download-zip` | 批量下载 (body: `{"files":[...]}`, 最多 100 项) |
| DELETE | `/files/:filename` | 删除文件 |
---
## 目录结构
```text
tmp-upload/
├── main.go # 入口、配置、路由注册 (61 行)
├── embed.go # //go:embed + init() 拼接 (38 行)
├── audit.go # 审计日志子系统 (102 行)
├── quota.go # 配额管理 + formatSize (112 行)
├── handlers.go # HTTP handlers + DTOs (440 行)
├── cleaner.go # TTL 过期清理 (57 行)
├── audit_test.go # audit 单元测试
├── security_test.sh # HTTP 端到端测试
├── go.mod / go.sum
└── static/
├── index.html.tpl # HTML 骨架 (含 /*EMBED_CSS*/、/*EMBED_JS*/ 占位符)
├── app.css # CSS (357 行)
├── app.js # JS — 主程序 (441 行)
├── helpers.js # JS — 纯函数 + 倒计时 (58 行)
└── batch.js # JS — 批量选择 / 批量下载 (87 行)
```
### 单文件部署说明
`embed.go` 用 `//go:embed` 把三个静态文件全部编入二进制,
在 `init()` 中用 `strings.Replace` 把 CSS/JS 拼到 HTML 骨架里生成 `pageHTML`。
浏览器访问 `/` 拿到的是**一个**完整 HTML 响应(HTML+CSS+JS 全部内联),
不产生额外的 `` / `