71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
|
|
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, LargeBinary
|
|||
|
|
from sqlalchemy.orm import relationship
|
|||
|
|
from datetime import datetime
|
|||
|
|
import os
|
|||
|
|
|
|||
|
|
from . import Base
|
|||
|
|
|
|||
|
|
class Attachment(Base):
|
|||
|
|
"""附件模型"""
|
|||
|
|
__tablename__ = 'attachments'
|
|||
|
|
|
|||
|
|
id = Column(Integer, primary_key=True)
|
|||
|
|
email_id = Column(Integer, ForeignKey('emails.id'), nullable=False, index=True)
|
|||
|
|
filename = Column(String(255), nullable=False)
|
|||
|
|
content_type = Column(String(100), nullable=True)
|
|||
|
|
size = Column(Integer, nullable=False, default=0)
|
|||
|
|
storage_path = Column(String(500), nullable=True) # 用于文件系统存储
|
|||
|
|
content = Column(LargeBinary, nullable=True) # 用于小型附件的直接存储
|
|||
|
|
created_at = Column(DateTime, default=datetime.utcnow)
|
|||
|
|
|
|||
|
|
# 关联关系
|
|||
|
|
email = relationship("Email", back_populates="attachments")
|
|||
|
|
|
|||
|
|
@property
|
|||
|
|
def is_stored_in_fs(self):
|
|||
|
|
"""判断附件是否存储在文件系统中"""
|
|||
|
|
return bool(self.storage_path and not self.content)
|
|||
|
|
|
|||
|
|
def save_to_filesystem(self, content, base_path):
|
|||
|
|
"""将附件保存到文件系统"""
|
|||
|
|
# 确保目录存在
|
|||
|
|
os.makedirs(base_path, exist_ok=True)
|
|||
|
|
|
|||
|
|
# 创建文件路径
|
|||
|
|
file_path = os.path.join(
|
|||
|
|
base_path,
|
|||
|
|
f"{self.email_id}_{self.id}_{self.filename}"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 写入文件
|
|||
|
|
with open(file_path, 'wb') as f:
|
|||
|
|
f.write(content)
|
|||
|
|
|
|||
|
|
# 更新对象属性
|
|||
|
|
self.storage_path = file_path
|
|||
|
|
self.size = len(content)
|
|||
|
|
self.content = None # 清空内存中的内容
|
|||
|
|
|
|||
|
|
return file_path
|
|||
|
|
|
|||
|
|
def get_content(self, attachments_dir=None):
|
|||
|
|
"""获取附件内容,无论是从数据库还是文件系统"""
|
|||
|
|
if self.content:
|
|||
|
|
return self.content
|
|||
|
|
|
|||
|
|
if self.storage_path and os.path.exists(self.storage_path):
|
|||
|
|
with open(self.storage_path, 'rb') as f:
|
|||
|
|
return f.read()
|
|||
|
|
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
def to_dict(self):
|
|||
|
|
"""转换为字典,用于API响应"""
|
|||
|
|
return {
|
|||
|
|
"id": self.id,
|
|||
|
|
"email_id": self.email_id,
|
|||
|
|
"filename": self.filename,
|
|||
|
|
"content_type": self.content_type,
|
|||
|
|
"size": self.size,
|
|||
|
|
"created_at": self.created_at.isoformat() if self.created_at else None
|
|||
|
|
}
|