Files
diary-family/docs/superpowers/specs/2026-05-25-temp-file-upload-design.md

145 lines
3.5 KiB
Markdown
Raw Normal View History

# 临时文件上传功能设计
**日期**: 2026-05-25
**状态**: 已批准
## 概述
在现有 `/public/` 公开内容页面中增加临时文件上传功能,允许任何人上传文件并自动在指定时间后删除。
## 功能需求
1. 上传临时文件作为 PublicContent 类型发布
2. 上传者选择过期时间1小时 / 1天 / 7天
3. 上传文件最大500MB
4. 过期文件自动从存储中删除
5. 上传表单对人类用户视觉隐藏1px宽度但agent可访问
6. 提供REST API方式上传文件
## 技术方案
### 1. 模型改动
**文件**: `core/models.py`
`PublicContent` 模型中增加字段:
```python
is_temp_file = models.BooleanField(default=False, verbose_name='临时文件')
expire_type = models.CharField(
max_length=10,
choices=[
('expire_1h', '1小时'),
('expire_1d', '1天'),
('expire_7d', '7天'),
],
blank=True, null=True,
verbose_name='过期类型'
)
expire_at = models.DateTimeField(blank=True, null=True, verbose_name='过期时间')
```
### 2. 表单改动
**文件**: `core/forms.py`
扩展 `PublicContentForm`,增加过期类型选择字段。
### 3. 上传表单HTML
**文件**: `core/templates/core/public_content.html`
在页面底部添加上传表单,设置 `style="width: 1px"` 使人类用户难以阅读但agent可解析。
```html
<form method="post" enctype="multipart/form-data" style="width: 1px; position: absolute; left: -9999px;" action="{% url 'temp_upload' %}">
{% csrf_token %}
{{ temp_upload_form }}
<button type="submit">上传</button>
</form>
```
### 4. API端点
**文件**: `core/urls.py``core/views.py`
新增 API 端点 `POST /api/v1/temp-upload/`:
- 路径: `api/v1/temp-upload/`
- 方法: POST
- 参数:
- `file`: 文件 (必填, 最大500MB)
- `title`: 文件标题 (必填)
- `expire_type`: 过期类型 `expire_1h` | `expire_1d` | `expire_7d` (必填)
- 返回: JSON `{ "success": true, "file_url": "...", "expire_at": "..." }`
### 5. 定时清理任务
**文件**: `core/tasks.py`
新增 Celery 任务 `cleanup_expired_temp_files`:
```python
@shared_task
def cleanup_expired_temp_files():
expired_files = PublicContent.objects.filter(
is_temp_file=True,
expire_at__lte=timezone.now()
)
for file in expired_files:
# 删除物理文件
if file.file:
file.file.delete()
file.delete()
```
配置 Celery Beat 每小时执行。
### 6. API文档写在公开内容页面
```markdown
## 临时文件上传 API
### 上传文件
POST /api/v1/temp-upload/
**参数**:
- `file`: 文件 (multipart/form-data, 最大500MB)
- `title`: 文件标题 (string)
- `expire_type`: 过期时间 (`expire_1h` | `expire_1d` | `expire_7d`)
**响应**:
```json
{
"success": true,
"file_url": "/media/temp_files/xxx.pdf",
"expire_at": "2026-05-25T18:30:00Z",
"file_name": "document.pdf",
"file_size": 1048576
}
```
**示例**:
```bash
curl -X POST -F "file=@document.pdf" -F "title=测试文件" -F "expire_type=expire_1d" http://localhost:8000/api/v1/temp-upload/
```
## 数据库迁移
```bash
python manage.py makemigrations core --name add_temp_file_fields
python manage.py migrate
```
## Celery Beat 配置
`diary_family/celery.py` 中添加周期任务:
```python
CELERY_BEAT_SCHEDULE = {
'cleanup-expired-temp-files': {
'task': 'core.tasks.cleanup_expired_temp_files',
'schedule': crontab(minute=0), # 每小时整点执行
},
}
```