Files
server/utils/upload_to.py
T
ngfchl 777ca50328 update. 完成前端页面展示、列表和详情页
update. 调整融合主菜单与板块
update. 分离新闻模块
2026-04-01 14:17:03 +08:00

96 lines
2.9 KiB
Python

import os
import hashlib
from datetime import datetime
def _get_file_md5(file_obj):
"""
通用辅助函数:计算任意文件对象的 MD5
"""
md5 = hashlib.md5()
# 关键步骤:重置文件指针到开头
# 因为 Django 在处理上传时可能已经读取了一部分文件头
try:
file_obj.seek(0)
except Exception:
pass
# 分块读取计算,防止大文件撑爆内存
for chunk in file_obj.chunks():
md5.update(chunk)
# 计算完后再次重置指针,确保不影响 Django 后续的保存操作
try:
file_obj.seek(0)
except Exception:
pass
return md5.hexdigest()
def upload_image_and_rename(instance, filename):
"""
通用图片上传处理函数
逻辑:存入 images/年/月/日/md5.ext
"""
# 1. 获取后缀
ext = os.path.splitext(filename)[1].lower()
# 2. 生成日期路径
date_str = datetime.now().strftime('%Y/%m/%d')
# 3. 计算 MD5
# 这里直接利用传入的 filename 对应的文件对象(在内存或临时文件中)
# 注意:这里假设 filename 是有效的 UploadedFile 对象名称,
# 但最稳妥的方式其实是直接操作 file_obj。
# 由于 upload_to 签名限制,我们通常通过 instance 获取字段值,
# 但为了通用性,我们尝试从 instance 的 __dict__ 中寻找 FileField 对象。
file_obj = None
# 遍历 instance 的所有属性,找到第一个 FileField 类型的值
for field in instance._meta.get_fields():
if hasattr(field, 'upload_to') and hasattr(instance, field.name):
val = getattr(instance, field.name)
if val and hasattr(val, 'chunks'): # 确认是文件对象
file_obj = val
break
# 如果找不到文件对象(极少见情况),使用随机字符串防止报错
if not file_obj:
import uuid
new_filename = f"{uuid.uuid4().hex}{ext}"
else:
md5_hash = _get_file_md5(file_obj)
new_filename = f"{md5_hash}{ext}"
# 4. 返回路径
return os.path.join('images', date_str, new_filename)
def upload_file_and_rename(instance, filename):
"""
通用文件上传处理函数
逻辑:存入 uploads/年/月/日/md5.ext
"""
ext = os.path.splitext(filename)[1].lower()
date_str = datetime.now().strftime('%Y/%m/%d')
file_obj = None
# 同样的通用查找逻辑
for field in instance._meta.get_fields():
if hasattr(field, 'upload_to') and hasattr(instance, field.name):
val = getattr(instance, field.name)
if val and hasattr(val, 'chunks'):
file_obj = val
break
if not file_obj:
import uuid
new_filename = f"{uuid.uuid4().hex}{ext}"
else:
md5_hash = _get_file_md5(file_obj)
new_filename = f"{md5_hash}{ext}"
return os.path.join('uploads', date_str, new_filename)