421 lines
10 KiB
Markdown
421 lines
10 KiB
Markdown
# 文件上传
|
||
|
||
FileCodeBox 提供了多种灵活的文件上传方式,支持普通上传和分片上传,满足不同场景的需求。
|
||
|
||
## 上传方式
|
||
|
||
FileCodeBox 支持以下几种上传方式:
|
||
|
||
### 拖拽上传
|
||
|
||
将文件直接拖拽到上传区域即可开始上传。这是最便捷的上传方式。
|
||
|
||
1. 打开 FileCodeBox 首页
|
||
2. 将文件从文件管理器拖拽到上传区域
|
||
3. 松开鼠标,文件开始上传
|
||
4. 上传完成后获取提取码
|
||
|
||
::: tip 提示
|
||
拖拽上传支持同时拖拽多个文件(取决于主题支持)。
|
||
:::
|
||
|
||
### 点击上传
|
||
|
||
点击上传区域,通过系统文件选择器选择文件。
|
||
|
||
1. 点击上传区域的「选择文件」按钮
|
||
2. 在弹出的文件选择器中选择要上传的文件
|
||
3. 确认选择后文件开始上传
|
||
4. 上传完成后获取提取码
|
||
|
||
### 粘贴上传
|
||
|
||
支持从剪贴板直接粘贴图片进行上传(部分主题支持)。
|
||
|
||
1. 复制图片到剪贴板(截图或复制图片)
|
||
2. 在上传区域使用 `Ctrl+V`(Windows/Linux)或 `Cmd+V`(macOS)粘贴
|
||
3. 图片自动开始上传
|
||
4. 上传完成后获取提取码
|
||
|
||
::: warning 注意
|
||
粘贴上传仅支持图片格式,不支持其他文件类型。具体支持情况取决于所使用的主题。
|
||
:::
|
||
|
||
## 文件大小限制
|
||
|
||
### 默认限制
|
||
|
||
| 配置项 | 默认值 | 说明 |
|
||
|--------|--------|------|
|
||
| `uploadSize` | 10MB | 单文件最大上传大小 |
|
||
|
||
### 修改上传限制
|
||
|
||
管理员可以通过管理面板或配置文件修改上传大小限制:
|
||
|
||
```python
|
||
# 设置最大上传大小为 100MB
|
||
uploadSize = 104857600 # 100 * 1024 * 1024
|
||
```
|
||
|
||
::: info 说明
|
||
`uploadSize` 的单位是字节。常用换算:
|
||
- 10MB = 10485760
|
||
- 50MB = 52428800
|
||
- 100MB = 104857600
|
||
- 500MB = 524288000
|
||
- 1GB = 1073741824
|
||
:::
|
||
|
||
### 超出限制的处理
|
||
|
||
当上传文件超过大小限制时,系统会返回 403 错误:
|
||
|
||
```json
|
||
{
|
||
"detail": "大小超过限制,最大为10.00 MB"
|
||
}
|
||
```
|
||
|
||
## 普通上传 API
|
||
|
||
### 文件上传接口
|
||
|
||
**POST** `/share/file/`
|
||
|
||
Content-Type: `multipart/form-data`
|
||
|
||
**请求参数:**
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `file` | file | 是 | 要上传的文件 |
|
||
| `expire_value` | int | 否 | 过期数值,默认 1 |
|
||
| `expire_style` | string | 否 | 过期方式,默认 `day` |
|
||
|
||
**过期方式选项:**
|
||
|
||
| 值 | 说明 |
|
||
|----|------|
|
||
| `day` | 按天过期 |
|
||
| `hour` | 按小时过期 |
|
||
| `minute` | 按分钟过期 |
|
||
| `forever` | 永不过期 |
|
||
| `count` | 按下载次数过期 |
|
||
|
||
**响应示例:**
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"detail": {
|
||
"code": "654321",
|
||
"name": "example.pdf"
|
||
}
|
||
}
|
||
```
|
||
|
||
**cURL 示例:**
|
||
|
||
```bash
|
||
# 上传文件(默认1天有效期)
|
||
curl -X POST "http://localhost:12345/share/file/" \
|
||
-F "file=@/path/to/file.pdf"
|
||
|
||
# 上传文件并指定有效期(7天)
|
||
curl -X POST "http://localhost:12345/share/file/" \
|
||
-F "file=@/path/to/file.pdf" \
|
||
-F "expire_value=7" \
|
||
-F "expire_style=day"
|
||
|
||
# 上传文件并指定有效期(可下载10次)
|
||
curl -X POST "http://localhost:12345/share/file/" \
|
||
-F "file=@/path/to/file.pdf" \
|
||
-F "expire_value=10" \
|
||
-F "expire_style=count"
|
||
|
||
# 分享文本
|
||
curl -X POST "http://localhost:12345/share/text/" \
|
||
-F "text=这是要分享的文本内容"
|
||
|
||
# 通过取件码下载文件
|
||
curl -L "http://localhost:12345/share/select/?code=取件码" -o downloaded_file
|
||
```
|
||
|
||
::: tip 需要认证时
|
||
如果管理面板关闭了游客上传(`openUpload=0`),需要先登录获取 token:
|
||
|
||
```bash
|
||
# 1. 登录获取 token
|
||
curl -X POST "http://localhost:12345/admin/login" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"password": "FileCodeBox2023"}'
|
||
|
||
# 返回: {"code":200,"msg":"success","detail":{"token":"xxx.xxx.xxx","token_type":"Bearer"}}
|
||
|
||
# 2. 使用 token 上传文件
|
||
curl -X POST "http://localhost:12345/share/file/" \
|
||
-H "Authorization: Bearer xxx.xxx.xxx" \
|
||
-F "file=@/path/to/file.pdf"
|
||
|
||
# 3. 使用 token 分享文本
|
||
curl -X POST "http://localhost:12345/share/text/" \
|
||
-H "Authorization: Bearer xxx.xxx.xxx" \
|
||
-F "text=这是要分享的文本内容"
|
||
```
|
||
:::
|
||
|
||
## 分片上传 API
|
||
|
||
对于大文件,FileCodeBox 支持分片上传功能。分片上传将大文件分割成多个小块分别上传,支持断点续传。
|
||
|
||
::: warning 前提条件
|
||
分片上传功能需要管理员启用:`enableChunk=1`
|
||
:::
|
||
|
||
### 分片上传流程
|
||
|
||
```
|
||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||
│ 初始化上传 │ ──▶ │ 上传分片 │ ──▶ │ 完成上传 │
|
||
│ /init/ │ │ /chunk/ │ │ /complete/ │
|
||
└─────────────┘ └─────────────┘ └─────────────┘
|
||
│
|
||
▼
|
||
┌───────────┐
|
||
│ 循环上传 │
|
||
│ 每个分片 │
|
||
└───────────┘
|
||
```
|
||
|
||
### 1. 初始化上传
|
||
|
||
**POST** `/chunk/upload/init/`
|
||
|
||
**请求参数:**
|
||
|
||
```json
|
||
{
|
||
"file_name": "large_file.zip",
|
||
"file_size": 104857600,
|
||
"chunk_size": 5242880,
|
||
"file_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||
}
|
||
```
|
||
|
||
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
||
|------|------|------|--------|------|
|
||
| `file_name` | string | 是 | - | 文件名 |
|
||
| `file_size` | int | 是 | - | 文件总大小(字节) |
|
||
| `chunk_size` | int | 否 | 5MB | 分片大小(字节) |
|
||
| `file_hash` | string | 是 | - | 文件的 SHA256 哈希值 |
|
||
|
||
**响应示例:**
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"detail": {
|
||
"existed": false,
|
||
"upload_id": "abc123def456789",
|
||
"chunk_size": 5242880,
|
||
"total_chunks": 20,
|
||
"uploaded_chunks": []
|
||
}
|
||
}
|
||
```
|
||
|
||
| 字段 | 说明 |
|
||
|------|------|
|
||
| `existed` | 文件是否已存在(秒传) |
|
||
| `upload_id` | 上传会话 ID |
|
||
| `chunk_size` | 分片大小 |
|
||
| `total_chunks` | 总分片数 |
|
||
| `uploaded_chunks` | 已上传的分片索引列表 |
|
||
|
||
### 2. 上传分片
|
||
|
||
**POST** `/chunk/upload/chunk/{upload_id}/{chunk_index}`
|
||
|
||
**路径参数:**
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `upload_id` | 初始化时返回的上传会话 ID |
|
||
| `chunk_index` | 分片索引,从 0 开始 |
|
||
|
||
**请求体:**
|
||
|
||
Content-Type: `multipart/form-data`
|
||
|
||
| 参数 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `chunk` | file | 分片数据 |
|
||
|
||
**响应示例:**
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"detail": {
|
||
"chunk_hash": "a1b2c3d4e5f6..."
|
||
}
|
||
}
|
||
```
|
||
|
||
**cURL 示例:**
|
||
|
||
```bash
|
||
# 上传第一个分片(索引为 0)
|
||
curl -X POST "http://localhost:12345/chunk/upload/chunk/abc123def456789/0" \
|
||
-F "chunk=@/path/to/chunk_0"
|
||
```
|
||
|
||
### 3. 完成上传
|
||
|
||
**POST** `/chunk/upload/complete/{upload_id}`
|
||
|
||
**路径参数:**
|
||
|
||
| 参数 | 说明 |
|
||
|------|------|
|
||
| `upload_id` | 上传会话 ID |
|
||
|
||
**请求参数:**
|
||
|
||
```json
|
||
{
|
||
"expire_value": 7,
|
||
"expire_style": "day"
|
||
}
|
||
```
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `expire_value` | int | 是 | 过期数值 |
|
||
| `expire_style` | string | 是 | 过期方式 |
|
||
|
||
**响应示例:**
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"detail": {
|
||
"code": "789012",
|
||
"name": "large_file.zip"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 断点续传
|
||
|
||
分片上传支持断点续传。当上传中断后:
|
||
|
||
1. 使用相同的 `file_hash` 重新调用初始化接口
|
||
2. 服务器返回 `uploaded_chunks` 列表,包含已上传的分片索引
|
||
3. 客户端只需上传不在列表中的分片
|
||
4. 所有分片上传完成后调用完成接口
|
||
|
||
**示例流程:**
|
||
|
||
```javascript
|
||
// 1. 初始化上传
|
||
const initResponse = await fetch('/chunk/upload/init/', {
|
||
method: 'POST',
|
||
body: JSON.stringify({
|
||
file_name: 'large_file.zip',
|
||
file_size: fileSize,
|
||
chunk_size: 5 * 1024 * 1024,
|
||
file_hash: fileHash
|
||
})
|
||
});
|
||
const { upload_id, uploaded_chunks, total_chunks } = await initResponse.json();
|
||
|
||
// 2. 上传未完成的分片
|
||
for (let i = 0; i < total_chunks; i++) {
|
||
if (!uploaded_chunks.includes(i)) {
|
||
const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize);
|
||
await fetch(`/chunk/upload/chunk/${upload_id}/${i}`, {
|
||
method: 'POST',
|
||
body: chunk
|
||
});
|
||
}
|
||
}
|
||
|
||
// 3. 完成上传
|
||
await fetch(`/chunk/upload/complete/${upload_id}`, {
|
||
method: 'POST',
|
||
body: JSON.stringify({
|
||
expire_value: 7,
|
||
expire_style: 'day'
|
||
})
|
||
});
|
||
```
|
||
|
||
## 错误处理
|
||
|
||
### 常见错误
|
||
|
||
| HTTP 状态码 | 错误信息 | 原因 | 解决方案 |
|
||
|-------------|----------|------|----------|
|
||
| 403 | 大小超过限制 | 文件超过 `uploadSize` 限制 | 减小文件大小或联系管理员调整限制 |
|
||
| 403 | 上传频率限制 | 超过 IP 上传频率限制 | 等待限制时间窗口后重试 |
|
||
| 400 | 过期时间类型错误 | `expire_style` 值不在允许列表中 | 使用有效的过期方式 |
|
||
| 404 | 上传会话不存在 | `upload_id` 无效或已过期 | 重新初始化上传 |
|
||
| 400 | 无效的分片索引 | `chunk_index` 超出范围 | 检查分片索引是否正确 |
|
||
| 400 | 分片不完整 | 完成上传时分片数量不足 | 确保所有分片都已上传 |
|
||
|
||
### 频率限制
|
||
|
||
系统对上传操作有频率限制,防止滥用:
|
||
|
||
| 配置项 | 默认值 | 说明 |
|
||
|--------|--------|------|
|
||
| `uploadMinute` | 1 | 限制时间窗口(分钟) |
|
||
| `uploadCount` | 10 | 时间窗口内最大上传次数 |
|
||
|
||
当超过频率限制时,需要等待时间窗口过后才能继续上传。
|
||
|
||
### 错误响应格式
|
||
|
||
```json
|
||
{
|
||
"detail": "错误信息描述"
|
||
}
|
||
```
|
||
|
||
## 上传配置
|
||
|
||
### 相关配置项
|
||
|
||
| 配置项 | 类型 | 默认值 | 说明 |
|
||
|--------|------|--------|------|
|
||
| `openUpload` | int | 1 | 是否开放上传(1=开放,0=关闭) |
|
||
| `uploadSize` | int | 10485760 | 最大上传大小(字节) |
|
||
| `enableChunk` | int | 0 | 是否启用分片上传(1=启用,0=禁用) |
|
||
| `uploadMinute` | int | 1 | 上传频率限制时间窗口(分钟) |
|
||
| `uploadCount` | int | 10 | 时间窗口内最大上传次数 |
|
||
| `expireStyle` | list | ["day","hour","minute","forever","count"] | 允许的过期方式 |
|
||
|
||
### 配置示例
|
||
|
||
```python
|
||
# 允许上传 100MB 文件,启用分片上传
|
||
uploadSize = 104857600
|
||
enableChunk = 1
|
||
|
||
# 放宽上传频率限制:每 5 分钟最多 50 次
|
||
uploadMinute = 5
|
||
uploadCount = 50
|
||
|
||
# 只允许按天和按次数过期
|
||
expireStyle = ["day", "count"]
|
||
```
|
||
|
||
## 下一步
|
||
|
||
- [文件分享](/guide/share) - 了解完整的分享流程
|
||
- [配置说明](/guide/configuration) - 了解所有配置选项
|
||
- [存储配置](/guide/storage) - 了解文件存储方式
|
||
- [安全设置](/guide/security) - 了解安全相关配置
|