# filebox **Repository Path**: ahaisong/filebox ## Basic Information - **Project Name**: filebox - **Description**: 文件寄存柜,文件上传托管寄存程序 - **Primary Language**: Java - **License**: AGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-22 - **Last Updated**: 2026-10-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # filebox 文件寄存柜 使用 Spring Boot 开发的临时文件上传托管寄存服务。上传文件后得到一个取件码,凭取件码即可下载文件;文件按到期日期归档,最长托管 30 天。应用密钥以文件形式存放在 `${base-dir}/keys/`,可使用管理密钥通过接口创建、修改、删除。 ## 运行环境 - JDK 8+ - Maven 3.6+ - nginx(生产环境,用于输出下载文件) ## 快速开始 ```bash mvn clean package java -jar target/filebox-1.0.0.jar ``` 默认监听 `8080` 端口,存放目录为 `/opt/filebox`。Windows 本地调试时可用环境变量覆盖: ```bash export FILEBOX_BASE_DIR=D:/filebox-data export FILEBOX_SECRET_KEY=your-secret mvn spring-boot:run ``` ## 配置 `src/main/resources/application.yml`: | 配置项 | 默认值 | 说明 | | --- |---------------| --- | | `filebox.base-dir` | `/opt/filebox` | 存放根目录,文件在 `${base-dir}/files`,取件码索引在 `${base-dir}/uuids` | | `filebox.secret-key` | `abcdef123` | **管理密钥**(master key),可调用密钥管理接口,本身也是合法上传密钥;**上线前务必修改** | | `filebox.default-days` | `1` | 未传密钥或密钥错误时的默认托管天数 | | `filebox.max-days` | `7` | 未传密钥或密钥错误时的最大托管天数 | | `filebox.secret-default-days` | `14` | 密钥正确(管理密钥或 `keys/` 下已存在)时的默认托管天数 | | `filebox.secret-max-days` | `30` | 密钥正确时的最大托管天数 | | `filebox.cleanup-cron` | `0 0 3 * * ?` | 清理任务执行时间,默认每天凌晨 3 点 | `filebox.base-dir`、`filebox.secret-key`、`filebox.cleanup-cron` 可分别通过环境变量 `FILEBOX_BASE_DIR`、`FILEBOX_SECRET_KEY`、`FILEBOX_CLEANUP_CRON` 覆盖。 ## 接口说明 ### 上传文件 `POST /upload` `multipart/form-data` 参数: | 参数 | 必传 | 说明 | | --- | --- | --- | | `file` | 是 | 上传的文件 | | `sk` | 否 | 密钥。等于管理密钥,或 `${base-dir}/keys/.txt` 存在时视为正确,默认托管 14 天;否则视为错误,默认 1 天 | | `days` | 否 | 托管天数;正确密钥最多 30 天,错误密钥最多 7 天,小于 1 按 1 处理,超出上限按上限处理 | 响应示例: ```json { "filename": "test.mp4", "code": "9b2f6c1e7d344a8e9f013c5d7e9a1b2c" } ``` 服务端处理逻辑: 1. 到期日期 = 上传日期 + 托管天数,例如 2026-01-01 托管 7 天即 2026-01-08; 2. 文件保存到 `${base-dir}/files/2026/01/08/`,文件名为 `UUID去横线 + "_" + 原始文件名`; 3. 生成取件码 `UUID.randomUUID().replace("-", "")`,并写入 `${base-dir}/uuids/<取件码>.txt`,内容为文件内部路径 `/files/2026/01/08/f47ac10b58cc4372a5670e02b2c3d479_test.mp4`。 示例: ```bash curl -F "file=@test.mp4" -F "sk=your-secret" -F "days=7" http://localhost:8080/upload ``` ### 下载文件 `GET /download?code=<取件码>` 按取件码找到 `${base-dir}/uuids/<取件码>.txt`,读取其中的内部路径并写入响应头: ```http X-Accel-Redirect: /files/2026/01/08/f47ac10b58cc4372a5670e02b2c3d479_test.mp4 ``` 文件内容由 nginx 在服务端内部读取并输出,`files` 目录不直接对公网开放。 示例: ```bash curl -OJ "http://localhost:8080/download?code=9b2f6c1e7d344a8e9f013c5d7e9a1b2c" ``` > 未经过 nginx 直接访问应用时,下载接口只会返回空的 200 响应和 `X-Accel-Redirect` 头,不会输出文件内容。 ## 密钥管理接口 密钥文件存放在 `${base-dir}/keys/<密钥>.txt`,内容为: ```json {"appId":"test001","remarks":"测试用的密钥001","role":"user"} ``` - `role` 等于 `admin` 的密钥权限与管理密钥相同,可以调用下列管理接口; - 上传时只要 `sk` 对应的密钥文件存在即视为正确密钥,不校验 `role`; - 管理接口通过请求头 `X-Admin-Key` 鉴权,可传管理密钥或 `role=admin` 的密钥。 | 方法 | 路径 | 说明 | | --- | --- | --- | | `POST` | `/keys` | 创建密钥。`appId` 必填,`remarks`、`role` 可选(`role` 默认 `user`),`key` 可选(不传则自动生成) | | `GET` | `/keys` | 列出全部密钥 | | `GET` | `/keys/{key}` | 查询单个密钥 | | `PUT` | `/keys/{key}` | 覆盖更新密钥内容 | | `DELETE` | `/keys/{key}` | 删除密钥 | 创建示例(服务端自动生成密钥): ```bash curl -X POST http://localhost:8080/keys \ -H "X-Admin-Key: your-secret" \ -H "Content-Type: application/json" \ -d '{"appId":"test001","remarks":"测试用的密钥001","role":"user"}' ``` ```json {"key":"f47ac10b58cc4372a5670e02b2c3d479","appId":"test001","remarks":"测试用的密钥001","role":"user"} ``` 也可以在请求体中增加 `"key":"f47ac10b58cc4372a5670e02b2c3d479"` 指定密钥。密钥必须为 32 个字符,只允许字母、数字、下划线、点和短横线,且不能以点开头。 更新示例: ```bash curl -X PUT http://localhost:8080/keys/f47ac10b58cc4372a5670e02b2c3d479 \ -H "X-Admin-Key: your-secret" \ -H "Content-Type: application/json" \ -d '{"appId":"test001","remarks":"已更新","role":"admin"}' ``` 错误响应:管理密钥无效 `401`,密钥不存在 `404`,密钥已存在 `409`,参数不合法 `400`。 ## nginx 配置 参考 [`deploy/nginx.conf.example`](deploy/nginx.conf.example): ```nginx location /files/ { internal; alias /opt/filebox/files/; } location / { proxy_pass http://127.0.0.1:8080; } ``` `alias` 指向的目录必须与 `filebox.base-dir` 下的 `files` 目录一致。 ## 目录结构 ``` /opt/filebox/ ├── files/ │ └── 2026/01/08/ │ └── f47ac10b58cc4372a5670e02b2c3d479_test.mp4 ├── uuids/ │ └── 9b2f6c1e7d344a8e9f013c5d7e9a1b2c.txt # 内容:/files/2026/01/08/f47ac10b58cc4372a5670e02b2c3d479_test.mp4 └── keys/ └── f47ac10b58cc4372a5670e02b2c3d479.txt # 内容:{"appId":"test001","remarks":"测试用的密钥001","role":"user"} ``` `keys` 目录同样不应由 nginx 直接对外暴露。 ## 定时清理 程序内置清理任务,默认每天凌晨 3 点执行一次(cron:`0 0 3 * * ?`,可通过 `filebox.cleanup-cron` 或 `FILEBOX_CLEANUP_CRON` 调整): - 删除日期早于今天的 `files/yyyy/MM/dd` 目录。例如 2026-04-20 执行时,删除 `2026/04/19` 及更早的目录,并清理因此变空的月份、年份目录; - 删除 `uuids/` 中内容无法解析、或指向的文件已不存在的 `<取件码>.txt`。 清理时先删除过期目录,再清理索引,因此过期文件对应的索引会一并删除;今天及未来日期的目录不受影响。执行时间与“今天”的判定均以服务器时区为准。 ## 测试 ```bash mvn test ```