fix: 增强图片上传错误处理和日志记录
This commit is contained in:
parent
ed07519b9d
commit
9a5b0828f7
@ -76,6 +76,7 @@ class ImageHandler:
|
||||
dict: 上传结果,包含 url, id, filename
|
||||
"""
|
||||
if not os.path.exists(image_path):
|
||||
self.pl.error(f"图片文件不存在:{image_path}")
|
||||
raise FileNotFoundError(f"图片文件不存在:{image_path}")
|
||||
|
||||
filename = os.path.basename(image_path)
|
||||
@ -92,16 +93,21 @@ class ImageHandler:
|
||||
with open(image_path, 'rb') as f:
|
||||
image_content = f.read()
|
||||
|
||||
self.dl.debug(f"图片文件大小:{len(image_content)} 字节")
|
||||
|
||||
# 获取 content_type
|
||||
content_type = self._get_content_type(image_path)
|
||||
|
||||
# 构建请求
|
||||
# 构建请求头 - 使用正确的 WordPress 媒体上传格式
|
||||
headers = {
|
||||
'Content-Disposition': f'attachment; filename="{filename}"',
|
||||
'Content-Type': content_type,
|
||||
'Content-Transfer-Encoding': 'binary'
|
||||
}
|
||||
|
||||
self.dl.debug(f"请求头:Content-Type={content_type}")
|
||||
self.dl.debug(f"请求头:Content-Disposition={headers['Content-Disposition']}")
|
||||
|
||||
# 上传图片
|
||||
response = requests.post(
|
||||
f'{self.wp_url}/wp-json/wp/v2/media',
|
||||
@ -112,6 +118,9 @@ class ImageHandler:
|
||||
timeout=30
|
||||
)
|
||||
|
||||
self.dl.debug(f"响应状态码:{response.status_code}")
|
||||
self.dl.debug(f"响应内容:{response.text[:200]}")
|
||||
|
||||
if response.status_code == 201:
|
||||
result = response.json()
|
||||
image_url = result.get('source_url', '')
|
||||
@ -143,9 +152,18 @@ class ImageHandler:
|
||||
else:
|
||||
error_msg = response.text
|
||||
self.pl.error(f"图片上传失败 - 状态码:{response.status_code}")
|
||||
self.pl.error(f"错误详情:{error_msg}")
|
||||
self.dl.error(f"上传失败:{error_msg}")
|
||||
raise Exception(f"图片上传失败:{error_msg}")
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
self.pl.error("图片上传请求超时")
|
||||
self.dl.error("图片上传请求超时")
|
||||
raise Exception("图片上传请求超时")
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
self.pl.error(f"图片上传连接错误:{str(e)}")
|
||||
self.dl.error(f"图片上传连接错误:{str(e)}")
|
||||
raise Exception(f"图片上传连接错误:{str(e)}")
|
||||
except Exception as e:
|
||||
self.pl.error(f"图片上传异常:{str(e)}")
|
||||
self.dl.error(f"上传异常:{str(e)}", exc_info=True)
|
||||
|
||||
309
modules/wp_image_handler.py.bak.20260514_004840
Normal file
309
modules/wp_image_handler.py.bak.20260514_004840
Normal file
@ -0,0 +1,309 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
WordPress 发布系统 - 图片处理模块
|
||||
处理图片保存、上传到 WordPress 媒体库
|
||||
"""
|
||||
|
||||
import os
|
||||
import base64
|
||||
import requests
|
||||
from io import BytesIO
|
||||
from PIL import Image
|
||||
|
||||
from modules.wp_logger import get_publish_logger, get_debug_logger
|
||||
|
||||
# 基础目录
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
TEMP_DIR = os.path.join(BASE_DIR, 'temp')
|
||||
os.makedirs(TEMP_DIR, exist_ok=True)
|
||||
|
||||
|
||||
class ImageHandler:
|
||||
"""图片处理器"""
|
||||
|
||||
def __init__(self, wp_url, wp_user, wp_password):
|
||||
"""
|
||||
初始化图片处理器
|
||||
|
||||
Args:
|
||||
wp_url: WordPress 站点 URL
|
||||
wp_user: WordPress 用户名
|
||||
wp_password: WordPress 应用密码
|
||||
"""
|
||||
self.wp_url = wp_url.rstrip('/')
|
||||
self.wp_user = wp_user
|
||||
self.wp_password = wp_password
|
||||
self.uploaded_images = {} # 记录已上传的图片
|
||||
|
||||
self.pl = get_publish_logger()
|
||||
self.dl = get_debug_logger()
|
||||
|
||||
def save_temp_image(self, image_data, filename):
|
||||
"""
|
||||
保存图片到临时目录
|
||||
|
||||
Args:
|
||||
image_data: 图片二进制数据
|
||||
filename: 文件名
|
||||
|
||||
Returns:
|
||||
str: 临时文件路径
|
||||
"""
|
||||
temp_path = os.path.join(TEMP_DIR, filename)
|
||||
|
||||
try:
|
||||
with open(temp_path, 'wb') as f:
|
||||
f.write(image_data)
|
||||
|
||||
self.dl.debug(f"图片已保存:{temp_path}")
|
||||
return temp_path
|
||||
|
||||
except Exception as e:
|
||||
self.dl.error(f"保存图片失败:{str(e)}")
|
||||
raise
|
||||
|
||||
def upload_image(self, image_path, title=None, alt_text=None):
|
||||
"""
|
||||
上传图片到 WordPress 媒体库
|
||||
|
||||
Args:
|
||||
image_path: 图片文件路径
|
||||
title: 图片标题
|
||||
alt_text: 图片 alt 文本
|
||||
|
||||
Returns:
|
||||
dict: 上传结果,包含 url, id, filename
|
||||
"""
|
||||
if not os.path.exists(image_path):
|
||||
raise FileNotFoundError(f"图片文件不存在:{image_path}")
|
||||
|
||||
filename = os.path.basename(image_path)
|
||||
if not title:
|
||||
title = os.path.splitext(filename)[0]
|
||||
if not alt_text:
|
||||
alt_text = title
|
||||
|
||||
self.pl.info(f"📤 上传图片:{filename}")
|
||||
self.dl.log_step("上传图片", f"文件:{filename}")
|
||||
|
||||
try:
|
||||
# 读取图片文件
|
||||
with open(image_path, 'rb') as f:
|
||||
image_content = f.read()
|
||||
|
||||
# 获取 content_type
|
||||
content_type = self._get_content_type(image_path)
|
||||
|
||||
# 构建请求
|
||||
headers = {
|
||||
'Content-Disposition': f'attachment; filename="{filename}"',
|
||||
'Content-Type': content_type,
|
||||
'Content-Transfer-Encoding': 'binary'
|
||||
}
|
||||
|
||||
# 上传图片
|
||||
response = requests.post(
|
||||
f'{self.wp_url}/wp-json/wp/v2/media',
|
||||
auth=(self.wp_user, self.wp_password),
|
||||
headers=headers,
|
||||
data=image_content,
|
||||
verify=False, # 跳过 SSL 验证
|
||||
timeout=30
|
||||
)
|
||||
|
||||
if response.status_code == 201:
|
||||
result = response.json()
|
||||
image_url = result.get('source_url', '')
|
||||
image_id = result.get('id', 0)
|
||||
|
||||
# 更新图片标题和 alt
|
||||
self._update_image_meta(image_id, title, alt_text)
|
||||
|
||||
self.pl.success(f"图片上传成功 - ID: {image_id}, URL: {image_url}")
|
||||
self.dl.log_result("上传结果", {
|
||||
'id': image_id,
|
||||
'url': image_url,
|
||||
'filename': filename
|
||||
})
|
||||
|
||||
# 记录已上传的图片
|
||||
self.uploaded_images[filename] = {
|
||||
'id': image_id,
|
||||
'url': image_url,
|
||||
'title': title
|
||||
}
|
||||
|
||||
return {
|
||||
'id': image_id,
|
||||
'url': image_url,
|
||||
'filename': filename,
|
||||
'title': title
|
||||
}
|
||||
else:
|
||||
error_msg = response.text
|
||||
self.pl.error(f"图片上传失败 - 状态码:{response.status_code}")
|
||||
self.dl.error(f"上传失败:{error_msg}")
|
||||
raise Exception(f"图片上传失败:{error_msg}")
|
||||
|
||||
except Exception as e:
|
||||
self.pl.error(f"图片上传异常:{str(e)}")
|
||||
self.dl.error(f"上传异常:{str(e)}", exc_info=True)
|
||||
raise
|
||||
|
||||
def upload_images_batch(self, images):
|
||||
"""
|
||||
批量上传图片
|
||||
|
||||
Args:
|
||||
images: 图片列表,每个图片包含 data, filename
|
||||
|
||||
Returns:
|
||||
list: 上传结果列表
|
||||
"""
|
||||
results = []
|
||||
|
||||
for i, image in enumerate(images):
|
||||
try:
|
||||
# 保存图片到临时目录
|
||||
temp_path = self.save_temp_image(image['data'], image['filename'])
|
||||
|
||||
# 上传图片
|
||||
result = self.upload_image(
|
||||
temp_path,
|
||||
title=f"图片 {i+1}",
|
||||
alt_text=f"文章配图 {i+1}"
|
||||
)
|
||||
|
||||
results.append(result)
|
||||
|
||||
# 清理临时文件
|
||||
if os.path.exists(temp_path):
|
||||
os.remove(temp_path)
|
||||
|
||||
except Exception as e:
|
||||
self.pl.error(f"图片 {i+1} 上传失败:{str(e)}")
|
||||
results.append({'error': str(e), 'filename': image['filename']})
|
||||
|
||||
return results
|
||||
|
||||
def generate_image_html(self, image_url, alt_text="", width=None):
|
||||
"""
|
||||
生成图片 HTML 标签
|
||||
|
||||
Args:
|
||||
image_url: 图片 URL
|
||||
alt_text: alt 文本
|
||||
width: 图片宽度(可选)
|
||||
|
||||
Returns:
|
||||
str: HTML img 标签
|
||||
"""
|
||||
style = "max-width: 100%; height: auto; display: block; margin: 16px auto;"
|
||||
if width:
|
||||
style += f" max-width: {width}px;"
|
||||
|
||||
html = f'<img src="{image_url}" alt="{alt_text}" style="{style}" loading="lazy">'
|
||||
return f'<figure style="text-align: center;">{html}</figure>'
|
||||
|
||||
def generate_featured_image_shortcode(self, image_url, alt_text=""):
|
||||
"""
|
||||
生成特色图片短代码
|
||||
|
||||
Args:
|
||||
image_url: 图片 URL
|
||||
alt_text: alt 文本
|
||||
|
||||
Returns:
|
||||
str: 特色图片 HTML
|
||||
"""
|
||||
return self.generate_image_html(image_url, alt_text)
|
||||
|
||||
def _update_image_meta(self, image_id, title, alt_text):
|
||||
"""更新图片元数据"""
|
||||
try:
|
||||
response = requests.post(
|
||||
f'{self.wp_url}/wp-json/wp/v2/media/{image_id}',
|
||||
auth=(self.wp_user, self.wp_password),
|
||||
json={
|
||||
'title': title,
|
||||
'alt_text': alt_text
|
||||
},
|
||||
verify=False,
|
||||
timeout=10
|
||||
)
|
||||
if response.status_code == 200:
|
||||
self.dl.debug(f"图片元数据更新成功:ID {image_id}")
|
||||
except Exception as e:
|
||||
self.dl.warning(f"更新图片元数据失败:{str(e)}")
|
||||
|
||||
def _get_content_type(self, file_path):
|
||||
"""获取图片 content_type"""
|
||||
ext = os.path.splitext(file_path)[1].lower()
|
||||
content_type_map = {
|
||||
'.jpg': 'image/jpeg',
|
||||
'.jpeg': 'image/jpeg',
|
||||
'.png': 'image/png',
|
||||
'.gif': 'image/gif',
|
||||
'.bmp': 'image/bmp',
|
||||
'.webp': 'image/webp',
|
||||
'.svg': 'image/svg+xml'
|
||||
}
|
||||
return content_type_map.get(ext, 'image/jpeg')
|
||||
|
||||
def optimize_image(self, image_path, max_width=1200, quality=85):
|
||||
"""
|
||||
优化图片大小
|
||||
|
||||
Args:
|
||||
image_path: 图片路径
|
||||
max_width: 最大宽度
|
||||
quality: 质量 (1-100)
|
||||
|
||||
Returns:
|
||||
str: 优化后的图片路径
|
||||
"""
|
||||
try:
|
||||
img = Image.open(image_path)
|
||||
|
||||
# 获取原始尺寸
|
||||
width, height = img.size
|
||||
|
||||
# 如果宽度超过限制,等比例缩放
|
||||
if width > max_width:
|
||||
ratio = max_width / width
|
||||
new_height = int(height * ratio)
|
||||
img = img.resize((max_width, new_height), Image.LANCZOS)
|
||||
self.dl.debug(f"图片已缩放:{width}x{height} -> {max_width}x{new_height}")
|
||||
|
||||
# 保存优化后的图片
|
||||
optimized_path = image_path.replace('.', '_optimized.')
|
||||
img.save(optimized_path, quality=quality, optimize=True)
|
||||
|
||||
return optimized_path
|
||||
|
||||
except Exception as e:
|
||||
self.dl.warning(f"图片优化失败:{str(e)}")
|
||||
return image_path
|
||||
|
||||
|
||||
def create_image_handler(wp_url, wp_user, wp_password):
|
||||
"""创建图片处理器实例"""
|
||||
return ImageHandler(wp_url, wp_user, wp_password)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 5:
|
||||
print("用法:python wp_image_handler.py <wp_url> <wp_user> <wp_password> <image_path>")
|
||||
sys.exit(1)
|
||||
|
||||
wp_url = sys.argv[1]
|
||||
wp_user = sys.argv[2]
|
||||
wp_password = sys.argv[3]
|
||||
image_path = sys.argv[4]
|
||||
|
||||
handler = create_image_handler(wp_url, wp_user, wp_password)
|
||||
result = handler.upload_image(image_path)
|
||||
print(f"上传结果:{result}")
|
||||
Loading…
Reference in New Issue
Block a user