diff --git a/src/infrastructure/scheduler/retry.py b/src/infrastructure/scheduler/retry.py index bcd1816..75b804f 100644 --- a/src/infrastructure/scheduler/retry.py +++ b/src/infrastructure/scheduler/retry.py @@ -161,21 +161,39 @@ class RetryManager: ) # Fix: html_render might return URL (str) even if return_url=False in some implementations - if isinstance(image_data, str) and image_data.startswith( - ("http://", "https://") - ): - logger.warning( - f"[RetryManager] html_render 返回了 URL 而不是 bytes,尝试下载: {image_data}" - ) - async with aiohttp.ClientSession() as session: - async with session.get(image_data) as resp: - if resp.status == 200: - image_data = await resp.read() + if isinstance(image_data, str): + if image_data.startswith(("http://", "https://")): + logger.warning( + f"[RetryManager] html_render 返回了 URL 而不是 bytes,尝试下载: {image_data}" + ) + async with aiohttp.ClientSession() as session: + async with session.get(image_data) as resp: + if resp.status == 200: + image_data = await resp.read() + else: + logger.error( + f"[RetryManager] 下载重试图片失败: {resp.status}" + ) + image_data = None + else: + # 本地文件路径 + try: + import os + if os.path.exists(image_data): + with open(image_data, "rb") as f: + image_data = f.read() + + # 校验文件头 (防御性编程,避免发送错误文本) + if not image_data.startswith(b"\xff\xd8") and not image_data.startswith(b"\x89PNG"): + if len(image_data) < 1024 and (b"Error" in image_data or b"Exception" in image_data): + logger.error(f"[RetryManager] 渲染器生成了错误文件而非图片: {image_data.decode('utf-8', errors='ignore')}") + return False else: - logger.error( - f"[RetryManager] 下载重试图片失败: {resp.status}" - ) + logger.error(f"[RetryManager] 渲染器返回的路径不存在: {image_data}") image_data = None + except Exception as e: + logger.error(f"[RetryManager] 读取本地图片失败: {e}") + image_data = None if not image_data: logger.warning(