Files
2025-10-14 20:05:29 +08:00

148 lines
4.7 KiB
Python

from pydantic import BaseModel, Field, validator
from typing import Optional, List
from datetime import datetime
import re
class FileUploadRequest(BaseModel):
"""文件上传请求"""
description: Optional[str] = Field(None, max_length=500, description="文件描述")
tags: Optional[str] = Field(None, max_length=200, description="文件标签,用逗号分隔")
is_public: bool = Field(False, description="是否公开分享")
@validator('tags')
def validate_tags(cls, v):
if v:
# 验证标签格式,只允许字母、数字、中文、下划线、中划线
tags = v.split(',')
for tag in tags:
tag = tag.strip()
if not re.match(r'^[\w\u4e00-\u9fa5-]+$', tag):
raise ValueError(f"标签 '{tag}' 格式不正确,只允许字母、数字、中文、下划线、中划线")
if len(tag) > 20:
raise ValueError(f"标签 '{tag}' 长度不能超过20个字符")
return v
class FileResponse(BaseModel):
"""文件响应"""
id: int
user_id: int
filename: str
original_filename: str
file_size: int
mime_type: str
file_hash: str
is_public: bool
download_count: int
description: Optional[str] = None
tags: Optional[str] = None
created_at: datetime
updated_at: datetime
last_accessed_at: Optional[datetime] = None
class Config:
from_attributes = True
class FileListResponse(BaseModel):
"""文件列表响应"""
files: List[FileResponse]
total: int
page: int
size: int
pages: int
class Config:
from_attributes = True
class FileListRequest(BaseModel):
"""文件列表请求"""
user_id: int = Field(..., description="用户ID")
page: int = Field(1, ge=1, description="页码")
size: int = Field(20, ge=1, le=100, description="每页数量")
class FileIdRequest(BaseModel):
"""文件ID请求"""
user_id: int = Field(..., description="用户ID")
file_id: int = Field(..., description="文件ID")
class StorageInfoRequest(BaseModel):
"""存储信息请求"""
user_id: int = Field(..., description="用户ID")
class FileUpdateRequest(BaseModel):
"""文件更新请求"""
description: Optional[str] = Field(None, max_length=500, description="文件描述")
tags: Optional[str] = Field(None, max_length=200, description="文件标签,用逗号分隔")
is_public: Optional[bool] = Field(None, description="是否公开分享")
@validator('tags')
def validate_tags(cls, v):
if v:
tags = v.split(',')
for tag in tags:
tag = tag.strip()
if not re.match(r'^[\w\u4e00-\u9fa5-]+$', tag):
raise ValueError(f"标签 '{tag}' 格式不正确,只允许字母、数字、中文、下划线、中划线")
if len(tag) > 20:
raise ValueError(f"标签 '{tag}' 长度不能超过20个字符")
return v
class FileSearchRequest(BaseModel):
"""文件搜索请求"""
filename: Optional[str] = Field(None, description="文件名搜索")
tags: Optional[str] = Field(None, description="标签搜索,用逗号分隔")
mime_type: Optional[str] = Field(None, description="MIME类型过滤")
is_public: Optional[bool] = Field(None, description="是否公开文件")
start_date: Optional[datetime] = Field(None, description="开始日期")
end_date: Optional[datetime] = Field(None, description="结束日期")
min_size: Optional[int] = Field(None, ge=0, description="最小文件大小(字节)")
max_size: Optional[int] = Field(None, ge=0, description="最大文件大小(字节)")
class FileInfo(BaseModel):
"""文件信息"""
id: int
filename: str
original_filename: str
file_size: int
mime_type: str
file_hash: str
is_image: bool
is_document: bool
file_extension: str
size_formatted: str
is_public: bool = False
download_count: int = 0
description: Optional[str] = None
tags: Optional[str] = None
created_at: datetime
updated_at: datetime
last_accessed_at: Optional[datetime] = None
class Config:
from_attributes = True
class UploadResponse(BaseModel):
"""文件上传响应"""
file_info: FileResponse
message: str
success: bool
class DeleteResponse(BaseModel):
"""删除文件响应"""
message: str
success: bool
class StorageInfo(BaseModel):
"""存储信息"""
total_quota: int
used_space: int
available_space: int
usage_percentage: float
file_count: int
# 通用API响应格式
class ApiResponse(BaseModel):
"""API响应"""
success: bool
message: str
data: Optional[dict] = None
code: Optional[str] = None