# 临时文件传输服务 基于 Flask 的个人临时文件分享服务,支持 Web 界面、API 接口和 SQLite 数据库。 ## 功能介绍 - 通过 Web 界面或 API 接口上传文件 - 选择过期时间:1 小时、24 小时或 7 天 - 生成分享链接(UUID)供下载使用 - 文件数据存储在磁盘,元数据存储在 SQLite - Web 下载页面和简单的 API 接口支持程序化上传 ## 技术栈 - Flask (Python) - SQLite (元数据存储) - 文件系统存储实际文件数据 ## 本地开发环境搭建 ### 1. 环境要求 - Python 3.8+ (当前环境使用 Python 3.x) - pip ### 2. 安装依赖 ```bash pip install -r requirements.txt ``` ### 3. 运行服务 ```bash python app.py ``` ### 4. 访问地址 - Web 界面: http://localhost:5000 - API 接口: 详见 /api/upload 和 /api/file 接口 ## 部署说明 生产环境部署信息: - **域名**: `xiaji-temp.duckdns.org` - **HTTPS**: Let's Encrypt SSL 证书,自动续期 (certbot timer) - **Nginx**: 反向代理,500MB 上传限制,80→443 自动跳转 - **Gunicorn**: 4 个工作者进程,systemd 管理 ## 项目结构 | 文件 | 说明 | |------|------| | `app.py` | Flask 应用程序主文件 | | `config.py` | 配置常量 | | `database.py` | SQLite 辅助函数和数据访问 | | `requirements.txt` | Python 依赖包 | | `templates/` | Jinja 模板 (index.html, download.html) | | `upload_client.py` | 简单的 API 客户端示例,用于测试 | | `uploads/` | 上传文件存储目录 (运行时创建) | | `temp_file_trans_client/` | PySide6 桌面客户端 | ## 桌面客户端 使用 Python + PySide6 + PyInstaller 构建的桌面客户端,支持拖拽上传文件。 ### 客户端功能 - 拖拽文件到指定区域上传 - 点击选择文件上传 - 显示上传进度 - 上传成功显示分享链接 - 支持复制链接到剪贴板 - 可配置服务器地址 ### 运行客户端 ```bash cd temp_file_trans_client pip install -r requirements.txt python main.py ``` ### 打包为 exe ```bash cd temp_file_trans_client pip install pyinstaller pyinstaller build.spec ``` 打包后的可执行文件位于 `dist/temp_file_trans_client.exe` ## 数据模型 (SQLite) **files 表结构:** | 字段 | 类型 | 说明 | |------|------|------| | id | TEXT PRIMARY KEY | 文件唯一标识 (UUID) | | filename | TEXT | 原始文件名 | | filepath | TEXT | 文件存储路径 | | filesize | INTEGER | 文件大小 (字节) | | expiry_hours | INTEGER | 过期时间 (小时) | | created_at | TIMESTAMP | 创建时间 | | expires_at | TIMESTAMP | 过期时间 | ## 过期清理 - 过期选项在 config 中定义为 1h、24h、7d - 清理操作会删除过期文件并清理数据库记录 - 访问接口时自动触发清理 (后续可配置 cron/定时任务) ## 流量限制 - 最大文件大小:500 MB - 单 IP 每日流量限制:20 GB (上传 + 下载合计) - IP 流量记录在 SQLite `ip_traffic` 表中,每日重置 ## SSL 证书 - 使用 Let's Encrypt 证书,通过 certbot 部署 - 自动续期通过 systemd timer: `certbot.timer` - 手动测试续期: `certbot renew --dry-run` ## 安全说明 - 请勿提交密钥等敏感信息。生产环境应通过环境变量提供 - 当前仓库未嵌入任何凭证 ## API 接口说明 ### 上传文件 ``` POST /api/upload Content-Type: multipart/form-data ``` **请求参数:** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | file | File | 是 | 要上传的文件 | | expiry | String | 否 | 过期时间: 1h / 24h / 7d (默认 24h) | **返回示例:** ```json { "id": "550e8400-e29b-41d4-a716-446655440000", "filename": "file.zip", "filesize": 1048576, "expiry_hours": 24, "share_url": "https://xiaji-temp.duckdns.org/file/550e8400..." } ``` ### 获取文件信息 ``` GET /api/file/{file_id} ``` **返回示例:** ```json { "id": "550e8400-e29b-41d4-a716-446655440000", "filename": "file.zip", "filesize": 1048576, "created_at": "2024-01-15 10:30:00", "expires_at": "2024-01-16 10:30:00", "daily_upload": 1048576, "daily_download": 0, "traffic_limit": 21474836480 } ``` ### 下载文件 ``` GET /file/{file_id} GET /download/{file_id} ``` ## Python API 调用示例 ### 上传文件 ```python import requests BASE_URL = "https://xiaji-temp.duckdns.org" expiry = "24h" # 可选: 1h, 24h, 7d with open("/path/to/your/file.zip", "rb") as f: resp = requests.post( f"{BASE_URL}/api/upload", files={"file": ("file.zip", f)}, data={"expiry": expiry}, verify=False # 对于自签名证书 ) if resp.status_code == 200: data = resp.json() print(f"分享链接: {data['share_url']}") print(f"文件 ID: {data['id']}") print(f"文件大小: {data['filesize']} bytes") else: print(f"上传失败: {resp.json()['error']}") ``` ### 获取文件信息 ```python resp = requests.get(f"{BASE_URL}/api/file/{file_id}", verify=False) if resp.status_code == 200: info = resp.json() print(f"每日上传: {info['daily_upload']} bytes") print(f"每日下载: {info['daily_download']} bytes") print(f"流量限制: {info['traffic_limit']} bytes (20GB)") ``` ## 使用客户端脚本 也可以直接使用附带的客户端脚本上传文件: ```bash python upload_client.py /path/to/file.zip 24h ``` ## 后续计划 - [ ] 添加管理员/API 认证 - [ ] 添加用户级别的速率限制和上传大小限制 - [ ] 添加自动化测试和 CI/CD 集成 ## 许可证 MIT 许可证 (或您偏好的许可证,按需更新) ## 联系方式 如需联系维护者,请使用您偏好的渠道。