[patch] 处理DY安装包打包后图片视频暂存路径部分权限问题

This commit is contained in:
2025-10-29 17:05:06 +08:00
parent 791f98bf61
commit a95278368d

View File

@@ -685,6 +685,12 @@ class DouYinMessageHandler:
self.sign_engine_initialized = False
self.sign_ctx = None
self.js_engine = None
# 🧹 启动时清理超过24小时的旧临时文件
self._cleanup_old_temp_files(max_age_hours=24)
# 🧹 设置定期清理任务每6小时清理一次
self._setup_periodic_cleanup()
# 打印实例创建信息
print(f"[DY Handler] 创建实例 {self.instance_id} for store {store_id}")
@@ -2079,8 +2085,9 @@ class DouYinMessageHandler:
continue
return None, None
# 保存到临时文件
temp_dir = os.path.join(os.path.dirname(__file__), "temp_uploads")
# 保存到临时文件(使用系统临时目录,兼容打包环境)
import tempfile
temp_dir = os.path.join(tempfile.gettempdir(), "shuidrop_temp_uploads")
os.makedirs(temp_dir, exist_ok=True)
# 🔥 修复:智能提取文件扩展名
@@ -2113,7 +2120,7 @@ class DouYinMessageHandler:
return None, None
def _cleanup_temp_file(self, file_path):
"""清理临时文件"""
"""清理单个临时文件"""
try:
if file_path and os.path.exists(file_path):
os.remove(file_path)
@@ -2121,6 +2128,76 @@ class DouYinMessageHandler:
except Exception as e:
self._log(f"⚠️ [DY上传] 删除临时文件失败: {e}", "WARNING")
def _cleanup_old_temp_files(self, max_age_hours=24):
"""
清理超过指定时间的旧临时文件
Args:
max_age_hours: 文件最大保留时间小时默认24小时
"""
try:
import tempfile
import time
temp_dir = os.path.join(tempfile.gettempdir(), "shuidrop_temp_uploads")
if not os.path.exists(temp_dir):
return
current_time = time.time()
max_age_seconds = max_age_hours * 3600
cleaned_count = 0
total_size = 0
# 遍历临时目录
for filename in os.listdir(temp_dir):
file_path = os.path.join(temp_dir, filename)
# 跳过目录
if not os.path.isfile(file_path):
continue
try:
# 检查文件修改时间
file_mtime = os.path.getmtime(file_path)
file_age = current_time - file_mtime
# 如果文件超过保留时间,删除
if file_age > max_age_seconds:
file_size = os.path.getsize(file_path)
os.remove(file_path)
cleaned_count += 1
total_size += file_size
self._log(f"🗑️ [清理] 删除过期临时文件: {filename} (已存在{file_age/3600:.1f}小时)", "DEBUG")
except Exception as e:
self._log(f"⚠️ [清理] 删除文件失败 {filename}: {e}", "WARNING")
continue
if cleaned_count > 0:
self._log(f"✅ [清理] 已清理 {cleaned_count} 个过期临时文件,释放空间: {total_size/(1024*1024):.2f}MB", "INFO")
else:
self._log(f"✅ [清理] 无需清理(所有临时文件都在保留期内)", "DEBUG")
except Exception as e:
self._log(f"⚠️ [清理] 清理旧临时文件失败: {e}", "WARNING")
def _setup_periodic_cleanup(self):
"""设置定期清理任务每6小时清理一次超过24小时的文件"""
import threading
def periodic_cleanup_task():
import time
while self.is_running:
# 每6小时清理一次
time.sleep(6 * 3600) # 6小时
if self.is_running:
self._cleanup_old_temp_files(max_age_hours=24)
# 在后台线程中运行定期清理任务
cleanup_thread = threading.Thread(target=periodic_cleanup_task, daemon=True, name="TempFileCleanup")
cleanup_thread.start()
self._log("🧹 [清理] 定期清理任务已启动每6小时执行一次", "DEBUG")
async def _get_upload_token(self, upload_type="image"):
"""获取上传Token图片或视频"""
try:
@@ -2209,14 +2286,15 @@ class DouYinMessageHandler:
if not upload_id:
return None
success = await self._upload_file_part(store_uri, authorization, image_path, step=2, upload_id=upload_id)
# 🔥 优化只读取一次文件计算CRC32并传递给step2和step3
with open(image_path, 'rb') as f:
file_content = f.read()
crc32_hex = format(zlib.crc32(file_content), '08x')
success = await self._upload_file_part(store_uri, authorization, image_path, step=2, upload_id=upload_id, file_content=file_content, crc=crc32_hex)
if not success:
return None
with open(image_path, 'rb') as f:
content = f.read()
crc32_hex = format(zlib.crc32(content), '08x')
success = await self._upload_file_part(store_uri, authorization, image_path, step=3, upload_id=upload_id, crc=crc32_hex)
if not success:
return None
@@ -2299,8 +2377,12 @@ class DouYinMessageHandler:
self._log(f"❌ [DY图片] {action}失败: {e}", "ERROR")
return None
async def _upload_file_part(self, uri, authorization, file_path, step, crc=None, upload_id=None):
"""上传图片文件分片(带超时和重试)"""
async def _upload_file_part(self, uri, authorization, file_path, step, crc=None, upload_id=None, file_content=None):
"""上传图片文件分片(带超时和重试)
Args:
file_content: 文件内容step=2时直接使用避免重复读取
"""
try:
headers = {
"Authorization": authorization,
@@ -2323,9 +2405,19 @@ class DouYinMessageHandler:
return response.json().get("payload", {}).get("uploadID")
elif step == 2:
with open(file_path, 'rb') as f:
content = f.read()
headers["Content-Crc32"] = format(zlib.crc32(content), '08x')
# 🔥 优化如果传入了file_content直接使用否则读取文件兼容旧代码
if file_content is None:
with open(file_path, 'rb') as f:
content = f.read()
else:
content = file_content
# 使用传入的crc或重新计算优先使用传入的
if crc:
headers["Content-Crc32"] = crc
else:
headers["Content-Crc32"] = format(zlib.crc32(content), '08x')
headers["Content-Length"] = str(len(content))
headers["Content-Type"] = 'application/octet-stream'
params = {"partNumber": "1", "uploadID": upload_id}