初次提交

This commit is contained in:
2025-10-14 20:05:29 +08:00
commit 6e4e48fdd2
673 changed files with 437006 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
from sqlalchemy import Column, Integer, String, BigInteger, DateTime, ForeignKey, Boolean, Text
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from app.core.database import Base
class File(Base):
__tablename__ = "files"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
# 文件基本信息
filename = Column(String(255), nullable=False, index=True)
original_filename = Column(String(255), nullable=False) # 用户上传时的原始文件名
file_path = Column(String(500), nullable=False) # 服务器上的存储路径
file_size = Column(BigInteger, nullable=False) # 文件大小(字节)
mime_type = Column(String(100), nullable=False) # 文件MIME类型
file_hash = Column(String(64), nullable=False, index=True) # SHA-256哈希用于去重和完整性检查
# 文件状态
is_public = Column(Boolean, default=False) # 是否公开分享
download_count = Column(BigInteger, default=0) # 下载次数
# 文件元数据
description = Column(Text, nullable=True) # 文件描述
tags = Column(Text, nullable=True) # 标签,用逗号分隔
# 时间戳
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
last_accessed_at = Column(DateTime(timezone=True), nullable=True)
# 关联关系
user = relationship("User", back_populates="files")
def __repr__(self):
return f"<File(id={self.id}, filename='{self.filename}', user_id={self.user_id})>"
def to_dict(self):
return {
"id": self.id,
"user_id": self.user_id,
"filename": self.filename,
"original_filename": self.original_filename,
"file_size": self.file_size,
"mime_type": self.mime_type,
"file_hash": self.file_hash,
"is_public": self.is_public,
"download_count": self.download_count,
"description": self.description,
"tags": self.tags,
"created_at": self.created_at.isoformat() if self.created_at else None,
"updated_at": self.updated_at.isoformat() if self.updated_at else None,
"last_accessed_at": self.last_accessed_at.isoformat() if self.last_accessed_at else None,
}
def get_file_extension(self) -> str:
"""获取文件扩展名"""
return self.filename.split('.')[-1].lower() if '.' in self.filename else ''
def is_image(self) -> bool:
"""判断是否为图片文件"""
return self.mime_type.startswith('image/')
def is_document(self) -> bool:
"""判断是否为文档文件"""
document_types = [
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.ms-powerpoint',
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'text/plain',
'text/csv'
]
return self.mime_type in document_types
def get_size_formatted(self) -> str:
"""获取格式化的文件大小"""
for unit in ['B', 'KB', 'MB', 'GB']:
if self.file_size < 1024.0:
return f"{self.file_size:.1f} {unit}"
self.file_size /= 1024.0
return f"{self.file_size:.1f} TB"