Files
zcglxt/FILE_MANAGEMENT_QUICKSTART.md
Claude e71181f0a3 fix: 修复多个关键问题
- 修复前端路由守卫:未登录时不显示提示,直接跳转登录页
- 修复API拦截器:401错误不显示提示,直接跳转
- 增强验证码显示:图片尺寸从120x40增加到200x80
- 增大验证码字体:从28号增加到48号
- 优化验证码字符:排除易混淆的0和1
- 减少干扰线:从5条减少到3条,添加背景色优化
- 增强登录API日志:添加详细的调试日志
- 增强验证码生成和验证日志
- 优化异常处理和错误追踪

影响文件:
- src/router/index.ts
- src/api/request.ts
- app/services/auth_service.py
- app/api/v1/auth.py
- app/schemas/user.py

测试状态:
- 前端构建通过
- 后端语法检查通过
- 验证码显示效果优化完成

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 00:26:21 +08:00

8.7 KiB
Raw Blame History

文件管理模块快速开始指南

🚀 快速开始

后端启动

1. 数据库迁移

cd C:/Users/Administrator/asset_management_backend

# 激活虚拟环境
python -m venv venv
venv\Scripts\activate  # Windows
# source venv/bin/activate  # Linux/Mac

# 安装依赖
pip install -r requirements.txt
pip install python-multipart pillow

# 运行迁移
alembic upgrade head

2. 创建上传目录

mkdir -p uploads/images
mkdir -p uploads/documents
mkdir -p uploads/thumbnails
mkdir -p uploads/temp

3. 启动服务

python run.py

后端服务将运行在 http://localhost:8000

前端启动

1. 安装依赖

cd C:/Users/Administrator/asset-management-frontend

npm install

2. 启动开发服务器

npm run dev

前端服务将运行在 http://localhost:5173

📝 API测试示例

1. 文件上传使用curl

# 上传文件
curl -X POST http://localhost:8000/api/v1/files/upload \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -F "file=@/path/to/your/file.jpg" \
  -F "remark=测试文件"

2. 获取文件列表

curl -X GET "http://localhost:8000/api/v1/files?page=1&page_size=20" \
  -H "Authorization: Bearer YOUR_TOKEN"

3. 下载文件

curl -X GET http://localhost:8000/api/v1/files/1/download \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -o downloaded_file.jpg

4. 生成分享链接

curl -X POST http://localhost:8000/api/v1/files/1/share \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"expire_days": 7}'

💻 前端使用示例

1. 在页面中使用文件上传组件

<template>
  <div>
    <file-upload
      :auto-upload="false"
      :show-progress="true"
      :show-image-preview="true"
      @upload-success="handleUploadSuccess"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import FileUpload from '@/components/file/FileUpload.vue'

const handleUploadSuccess = (response, file) => {
  ElMessage.success(`文件 ${file.name} 上传成功`)
  console.log('上传响应:', response)
}
</script>

2. 在页面中使用文件列表组件

<template>
  <div>
    <file-list />
  </div>
</template>

<script setup>
import FileList from '@/components/file/FileList.vue'
</script>

3. 使用文件API

import { uploadFile, getFileList, downloadFile } from '@/api/file'

// 上传文件
const handleUpload = async (file: File) => {
  try {
    const response = await uploadFile(file, { remark: '测试' })
    console.log('上传成功:', response)
  } catch (error) {
    console.error('上传失败:', error)
  }
}

// 获取文件列表
const fetchFiles = async () => {
  try {
    const files = await getFileList({
      page: 1,
      page_size: 20,
      keyword: 'test'
    })
    console.log('文件列表:', files)
  } catch (error) {
    console.error('获取失败:', error)
  }
}

// 下载文件
const handleDownload = async (fileId: number, fileName: string) => {
  try {
    await downloadFile(fileId)
    // 注意:实际下载需要在响应头处理
    window.open(`http://localhost:8000/api/v1/files/${fileId}/download`)
  } catch (error) {
    console.error('下载失败:', error)
  }
}

🎯 常见功能实现

1. 批量上传

<template>
  <file-upload
    :multiple="true"
    :limit="10"
    :auto-upload="false"
    ref="uploadRef"
  >
    <template #tip>
      <div>最多可上传10个文件</div>
    </template>
  </file-upload>

  <el-button @click="submitUpload">开始上传</el-button>
</template>

<script setup>
import { ref } from 'vue'
import FileUpload from '@/components/file/FileUpload.vue'

const uploadRef = ref()

const submitUpload = () => {
  uploadRef.value.submitUpload()
}
</script>

2. 图片预览

<template>
  <div>
    <el-button @click="showPreview = true">预览图片</el-button>

    <image-preview
      v-model:visible="showPreview"
      :images="images"
      :initial-index="0"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import ImagePreview from '@/components/file/ImagePreview.vue'

const showPreview = ref(false)
const images = ref([
  {
    url: 'http://localhost:8000/api/v1/files/1/preview',
    name: '图片1.jpg'
  },
  {
    url: 'http://localhost:8000/api/v1/files/2/preview',
    name: '图片2.jpg'
  }
])
</script>

3. 文件分享

import { createShareLink } from '@/api/file'
import { ElMessage } from 'element-plus'

const shareFile = async (fileId: number) => {
  try {
    const result = await createShareLink(fileId, 7) // 7天有效期
    ElMessage.success(`分享链接: ${result.share_url}`)

    // 复制到剪贴板
    navigator.clipboard.writeText(result.share_url)
  } catch (error) {
    ElMessage.error('生成分享链接失败')
  }
}

4. 大文件分片上传

import { initChunkUpload, uploadChunk, completeChunkUpload } from '@/api/file'

const uploadLargeFile = async (file: File) => {
  const CHUNK_SIZE = 5 * 1024 * 1024 // 5MB每片
  const totalChunks = Math.ceil(file.size / CHUNK_SIZE)

  // 1. 初始化
  const { upload_id } = await initChunkUpload({
    file_name: file.name,
    file_size: file.size,
    file_type: file.type,
    total_chunks: totalChunks
  })

  // 2. 上传分片
  for (let i = 0; i < totalChunks; i++) {
    const start = i * CHUNK_SIZE
    const end = Math.min(start + CHUNK_SIZE, file.size)
    const chunk = file.slice(start, end)

    await uploadChunk(upload_id, i, chunk)
    console.log(`分片 ${i + 1}/${totalChunks} 上传完成`)
  }

  // 3. 完成上传
  const result = await completeChunkUpload({
    upload_id: upload_id,
    file_name: file.name
  })

  console.log('上传完成:', result)
}

🔍 API响应示例

上传文件响应

{
  "id": 1,
  "file_name": "a1b2c3d4-e5f6-7890-abcd-ef1234567890.jpg",
  "original_name": "photo.jpg",
  "file_size": 1024000,
  "file_type": "image/jpeg",
  "file_path": "uploads/2026/01/24/a1b2c3d4-e5f6-7890-abcd-ef1234567890.jpg",
  "download_url": "http://localhost:8000/api/v1/files/1/download",
  "preview_url": "http://localhost:8000/api/v1/files/1/preview",
  "message": "上传成功"
}

文件列表响应

[
  {
    "id": 1,
    "file_name": "uuid.jpg",
    "original_name": "photo.jpg",
    "file_size": 1024000,
    "file_type": "image/jpeg",
    "file_ext": "jpg",
    "uploader_id": 1,
    "uploader_name": "张三",
    "upload_time": "2026-01-24T10:30:00",
    "thumbnail_path": "uploads/thumbnails/2026/01/24/thumb_uuid.jpg",
    "download_count": 5,
    "remark": null
  }
]

分享链接响应

{
  "share_code": "AbCdEf1234567890",
  "share_url": "http://localhost:8000/api/v1/files/share/AbCdEf1234567890",
  "expire_time": "2026-01-31T10:30:00"
}

文件统计响应

{
  "total_files": 150,
  "total_size": 524288000,
  "total_size_human": "500.00 MB",
  "type_distribution": {
    "image/jpeg": 80,
    "image/png": 40,
    "application/pdf": 30
  },
  "upload_today": 10,
  "upload_this_week": 50,
  "upload_this_month": 120,
  "top_uploaders": [
    { "uploader_id": 1, "count": 50 },
    { "uploader_id": 2, "count": 30 }
  ]
}

🛠️ 故障排除

问题1上传文件失败

错误信息413 Request Entity Too Large

解决方案 检查Nginx配置如果使用

client_max_body_size 100M;

问题2文件类型不支持

错误信息不支持的文件类型

解决方案app/services/file_service.py 中添加文件类型到白名单:

ALLOWED_MIME_TYPES = {
    'image/webp',  # 添加新类型
    # ... 其他类型
}

问题3缩略图生成失败

错误信息生成缩略图失败

解决方案 确保安装了Pillow库

pip install pillow

问题4前端无法预览图片

错误信息CORS错误

解决方案 在后端添加CORS中间件

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:5173"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

📚 更多资源

💡 提示

  1. 开发环境:使用小文件测试,避免上传大文件
  2. 生产环境建议使用云存储服务OSS、S3等
  3. 安全性:生产环境务必配置文件类型和大小限制
  4. 性能:大文件使用分片上传,提高上传成功率
  5. 监控:记录文件上传、下载日志,便于问题追踪

如有问题,请查看完整文档或联系开发团队。