实现上传功能

This commit is contained in:
2025-10-28 17:22:27 +08:00
parent 1062bcfb70
commit 74df0e539c
15 changed files with 1126 additions and 24 deletions
+203
View File
@@ -0,0 +1,203 @@
# 文件上传功能文档
## 概述
文件上传功能已完整实现,支持将文件保存到本地文件系统并记录到数据库中。
## 功能特性
1. **自动目录管理**:按年月日自动创建目录结构(如 `front/uploads/2024/01/15/`
2. **唯一文件名**:使用时间戳生成唯一文件名,避免重名冲突
3. **文件类型识别**:自动识别文件类型(图片、文档、视频、音频、压缩包等)
4. **数据库记录**:所有文件信息保存到 `yz_files`
5. **用户关联**:自动关联当前登录用户
6. **异常处理**:文件保存失败时自动清理已上传的文件
## 文件结构
```
front/
└── uploads/
├── 2024/
│ ├── 01/
│ │ ├── 15/
│ │ │ ├── 20240115143045_example.jpg
│ │ │ └── 20240115143046_document.pdf
```
## API 接口
### 上传文件
**POST** `/api/files`
**请求头**:
```
Authorization: Bearer <token>
Content-Type: multipart/form-data
```
**请求参数**:
- `file` (File, required): 上传的文件
- `category` (String, optional): 文件分类,默认为"未分类"
- `tenant_id` (String, optional): 租户ID,默认为"default"
**响应示例**:
```json
{
"success": true,
"message": "文件上传成功",
"data": {
"id": 1,
"tenant_id": "default",
"user_id": 123,
"file_name": "example",
"original_name": "example.jpg",
"file_path": "uploads/2024/01/15/20240115143045_example.jpg",
"file_url": "/uploads/2024/01/15/20240115143045_example.jpg",
"file_size": 102400,
"file_type": "image",
"file_ext": ".jpg",
"category": "未分类",
"upload_by": "username",
"upload_time": "2024-01-15T14:30:45Z"
}
}
```
## 后端实现
### 路由配置
`server/routers/router.go` 中配置:
```go
// 文件管理路由
beego.Router("/api/files", &controllers.FileController{}, "get:GetAllFiles")
beego.Router("/api/files", &controllers.FileController{}, "post:Post")
beego.Router("/api/files/my", &controllers.FileController{}, "get:GetMyFiles")
beego.Router("/api/files/:id", &controllers.FileController{}, "get:GetFileById")
beego.Router("/api/files/:id", &controllers.FileController{}, "put:UpdateFile")
beego.Router("/api/files/:id", &controllers.FileController{}, "delete:DeleteFile")
```
### 控制器实现
`Post()` 方法位于 `server/controllers/file.go`:
1. 验证用户登录状态
2. 接收上传的文件
3. 生成日期路径和唯一文件名
4. 保存文件到本地
5. 记录文件信息到数据库
6. 返回文件信息
## 前端使用
### 基本用法
```typescript
import { fileAPI } from '@/api/file'
// 创建 FormData
const formData = new FormData()
formData.append('file', fileObject) // fileObject 是 File 对象
formData.append('category', '文档')
formData.append('tenant_id', 'tenant-001')
// 上传文件
try {
const response = await fileAPI.uploadFile(formData, {
category: '文档',
tenantId: 'tenant-001'
})
console.log('上传成功:', response.data)
} catch (error) {
console.error('上传失败:', error)
}
```
### Element Plus 上传组件
```vue
<el-upload
ref="uploadRef"
drag
:action="uploadUrl"
:headers="uploadHeaders"
:data="{ category: uploadForm.category }"
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
:before-upload="beforeUpload"
multiple
>
<el-icon><upload-filled /></el-icon>
<div class="el-upload__text">
将文件拖到此处<em>点击上传</em>
</div>
</el-upload>
<script setup>
const uploadUrl = computed(() => {
const baseUrl = import.meta.env.VITE_API_BASE_URL
return `${baseUrl}/api/files`
})
const uploadHeaders = computed(() => {
const token = localStorage.getItem('token')
return {
'Authorization': `Bearer ${token}`
}
})
const handleUploadSuccess = (response) => {
console.log('上传成功:', response)
}
const beforeUpload = (file) => {
const maxSize = 10 * 1024 * 1024 // 10MB
if (file.size > maxSize) {
ElMessage.error('文件大小不能超过 10MB')
return false
}
return true
}
</script>
```
## 文件访问
上传后的文件可以通过以下URL访问:
```
http://localhost:8080/uploads/2024/01/15/20240115143045_example.jpg
```
注意:需要配置 Beego 的静态文件服务来提供上传文件的访问。
`server/conf/app.conf` 中添加:
```conf
# 文件上传目录
StaticDir = /uploads:../front/uploads
```
## 安全注意事项
1. **文件大小限制**:建议在前端和后端都添加文件大小限制
2. **文件类型验证**:根据业务需求限制允许上传的文件类型
3. **文件名安全**:避免用户控制文件名造成安全问题
4. **权限控制**:确保只有授权用户可以上传文件
5. **存储位置**:考虑使用对象存储服务(如 OSS、S3)替代本地存储
## 数据库字段说明
`yz_files` 表的主要字段:
- `file_path`: 相对路径,用于存储和访问文件
- `file_url`: 访问URL
- `original_name`: 用户上传时的原始文件名
- `file_name`: 去除扩展名的文件名
- `file_type`: 文件类型(image, document, video, audio, archive, other
- `category`: 用户自定义分类
+164
View File
@@ -0,0 +1,164 @@
# 文件上传路径说明
## 当前配置
### 文件保存路径
文件保存在项目根目录的 `front/uploads/` 目录下,按照日期自动分类:
```
项目根目录/
├── server/
│ └── controllers/
│ └── file.go (处理上传)
├── front/
│ └── uploads/ ← 文件保存位置
│ ├── 2024/
│ │ └── 01/
│ │ └── 15/
│ │ └── 20240115143045_example.jpg
```
### 代码中的路径
`server/controllers/file.go``Post()` 方法中:
```go
// 构造保存路径:../front/uploads/年/月/日/
uploadDir := path.Join("..", "front", "uploads", datePath)
```
**说明**
- `..` 表示从 server 目录向上一级到项目根目录
- `front/uploads/` 是上传文件的根目录
- `datePath` 是按日期自动生成的子目录(如 `2024/01/15`
### 静态文件访问配置
`server/conf/app.conf` 中:
```conf
StaticDir = /uploads:../front/uploads
```
**说明**
- `/uploads` 是 URL 访问路径
- `../front/uploads` 是实际文件存储路径(相对于 server 目录)
## 目录结构
### 保存到数据库的路径
- `file_path`: `uploads/2024/01/15/20240115143045_example.jpg`(相对路径)
- `file_url`: `/uploads/2024/01/15/20240115143045_example.jpg`URL 路径)
### 实际文件系统路径
```
front/uploads/2024/01/15/20240115143045_example.jpg
```
### 访问 URL
```
http://localhost:8080/uploads/2024/01/15/20240115143045_example.jpg
```
## 为什么使用相对路径 `..`
由于项目结构是:
```
yunzer_go/
├── server/ ← 服务端代码
└── front/ ← 前端代码和上传文件
└── uploads/
```
`server` 目录运行应用时,要访问 `front/uploads`,需要使用 `../front/uploads`
## 如果路径不对怎么办?
### 方案1:修改代码中的路径
如果您的项目启动目录不同,可以修改 `file.go` 中的路径:
```go
// 如果从项目根目录运行
uploadDir := path.Join("front", "uploads", datePath)
// 或者使用绝对路径
uploadDir := path.Join("/path/to/project", "front", "uploads", datePath)
```
### 方案2:从配置文件读取
`app.conf` 中添加配置:
```conf
# 上传文件目录
uploadDir = ../front/uploads
```
然后在代码中读取:
```go
import "github.com/beego/beego/v2/server/web"
uploadDir := path.Join(
web.AppConfig.String("uploadDir"),
datePath,
)
```
## 验证路径是否正确
### 1. 检查文件保存位置
上传一个文件后,查看文件是否在正确的位置:
```bash
ls front/uploads/
```
应该看到按日期分类的文件夹和文件。
### 2. 检查数据库记录
查看 `yz_files` 表中的 `file_path` 字段:
```sql
SELECT file_path, file_url FROM yz_files ORDER BY upload_time DESC LIMIT 1;
```
应该看到类似:
```
file_path: uploads/2024/01/15/20240115143045_example.jpg
file_url: /uploads/2024/01/15/20240115143045_example.jpg
```
### 3. 检查 URL 访问
直接在浏览器访问:
```
http://localhost:8080/uploads/2024/01/15/文件名
```
如果能看到文件,说明路径配置正确。
## 常见问题
### Q: 文件保存在了 server/front/uploads
A: 修改代码中的路径为 `../front/uploads`(已经修改)
### Q: 文件保存在了 front/front/uploads
A: 检查当前工作目录,确保在 server 目录运行应用
### Q: 访问文件返回 404
A: 检查 `app.conf` 中的 StaticDir 配置是否正确
### Q: 权限问题?
A: 确保应用有创建目录和写入文件的权限:
```bash
chmod 755 front/uploads
```
## 建议的改进
如果需要更可靠的路径处理,可以考虑:
1. **使用绝对路径**:从配置文件或环境变量读取项目根目录
2. **路径验证**:在应用启动时检查上传目录是否存在,不存在则创建
3. **日志记录**:记录文件保存的完整路径,便于调试