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

145 lines
3.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 临时文件上传功能设计
**日期**: 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), # 每小时整点执行
},
}
```