yunzer_go/server/docs/FILE_UPLOAD.md
2025-10-28 17:22:27 +08:00

5.1 KiB
Raw Permalink Blame History

文件上传功能文档

概述

文件上传功能已完整实现,支持将文件保存到本地文件系统并记录到数据库中。

功能特性

  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"

响应示例:

{
  "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 中配置:

// 文件管理路由
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. 返回文件信息

前端使用

基本用法

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 上传组件

<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 中添加:

# 文件上传目录
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: 用户自定义分类