xnx_webp — WebP 压缩
Xiuno X 插件:上传图片时自动转换为 WebP 格式,显著减小图片体积,提升页面加载速度。
功能特性
自动转换:用户上传图片时自动转换为 WebP 格式,无需手动操作
双引擎支持:优先使用 Imagick(质量更好),降级使用 PHP GD 扩展
等比例缩放:超过最大宽高时按比例缩放,不拉伸变形
透明通道保留:PNG / GIF / BMP 转换后保留透明背景
智能跳过:
服务器不支持 WebP 时跳过(使用原图)
文件小于阈值(默认 100KB)时跳过
GIF 动图默认跳过(可配置开启)
已是 WebP 格式跳过
失败降级:转换失败时记录日志并使用原图,不中断上传流程
全局覆盖:覆盖所有走
attach-create路由的上传场景(发帖、回帖、编辑器插图、应用中心截图等)
环境要求
Xiuno X(BBS 1.0+)
PHP 7.0+(推荐 PHP 8.0+)
至少安装以下任一扩展:
Imagick(推荐,质量更好)
PHP GD 扩展(需编译时启用 WebP 支持,
imagewebp()函数可用)
检测命令:
php -m | grep -E "imagick|gd"
php -r "var_dump(function_exists('imagewebp'));"
安装
将
xnx_webp目录放入plugin/登录后台 → 插件管理 → 找到「WebP 压缩」→ 点击「安装」并「启用」
(生产环境 DEBUG=0)清理编译缓存:
rm -f tmp/route_attach.php tmp/model.min.php tmp/lang_*_bbs.php进入
admin/?plugin-setting-xnx_webp.htm配置参数
后台配置项
配置项 | 说明 | 默认值 |
|---|---|---|
启用 WebP 转换 | 全局开关 | 开 |
压缩质量 | 1-100,数值越大质量越好体积越大 | 80 |
最大宽度 | 像素,超过则等比缩放,0 表示不限制 | 1920 |
最大高度 | 像素,超过则等比缩放,0 表示不限制 | 1920 |
转换 GIF 动图 | 是否将 GIF 动图转为 WebP(默认关闭,保留动图) | 关 |
最小文件大小 | KB,小于此值的图片不转换 | 100 |
支持的源格式
格式 | MIME | Imagick | GD |
|---|---|---|---|
JPEG | image/jpeg | ✅ | ✅ |
PNG | image/png | ✅ | ✅ |
GIF | image/gif | ✅ | ✅ |
BMP | image/bmp | ✅ | PHP 7.2+ |
WebP | image/webp | 跳过 | 跳过 |
工作原理
插件通过 attach_create_save_before hook 注入到 route/attach.php 的上传流程中:
用户上传图片
↓
route/attach.php 接收请求
↓
[hook] attach_create_save_before.php 拦截
↓
WebpService::convert() 转换为 WebP
↓
file_put_contents 写回 $_FILES['file']['tmp_name']
↓
同步更新 $name / $ext / $size / $tmpname / $tmpfile / $tmpurl
↓
move_uploaded_file 移动到最终位置
转换后的文件名后缀会自动改为 .webp(如 photo.jpg → photo.webp),确保用户下载后能用图片查看器正常打开。
覆盖场景
插件覆盖所有走 attach-create 路由(FormData 模式)的上传场景:
✅ 发帖/回帖上传图片
✅ 富文本编辑器(AIEditor / wangEditor)上传图片
✅ xnx_attach 插件附件上传
✅ xnx_appcenter 应用截图上传
✅ 其他任何通过系统上传接口的图片
不覆盖的场景(保持原格式):
头像上传(固定后缀,转换会导致 MIME 不匹配)
勋章图标上传(固定后缀)
降级与容错
场景 | 行为 |
|---|---|
服务器未装 Imagick 和 GD | 后台设置页显示红色警告,上传流程使用原图 |
单次转换失败 | 记录 |
图片损坏无法读取 |
|
GIF 动图(默认配置) | 保留原 GIF 格式不动 |
文件结构
plugin/xnx_webp/
├── conf.json # 插件配置
├── install.php # 安装脚本(初始化默认配置)
├── uninstall.php # 卸载脚本(清理 setting)
├── setting.php # 后台设置处理
├── icon.png # 插件图标
├── README.md # 本文档
├── model/
│ └── WebpService.php # 核心转换类
├── view/htm/
│ └── setting.htm # 后台设置页模板
└── hook/
├── attach_create_save_before.php # 上传前拦截 hook
├── model_inc_file.php # 注册 Service 到核心
├── lang_zh_cn_bbs.php # 简体中文
├── lang_zh_tw_bbs.php # 繁体中文
└── lang_en_us_bbs.php # 英文
验证转换效果
启用插件后上传一张 JPEG/PNG 图片,访问帖子详情页右键图片 → 「在新标签页打开图片」,URL 应以 .webp 结尾。
或在服务器查看:
ls -la upload/attach/<YYYY-MM>/<uid>/
# 应看到 .webp 后缀的文件
常见问题
Q: 后台设置页显示「不支持」?
A: 服务器未安装 Imagick 或 GD 扩展。安装方式:
Imagick:
apt install php-imagick(Debian/Ubuntu)或pecl install imagickGD with WebP:编译 PHP 时加
--with-webp参数,或apt install php-gd(确认版本支持 WebP)
Q: 上传后图片没有变成 WebP?
A: 排查顺序:
确认插件已启用且「启用 WebP 转换」开关打开
确认图片大小超过「最小文件大小」阈值(默认 100KB)
确认不是 GIF 动图(默认不转换)
清理
tmp/编译缓存后重试查看
xiunobbs-master/log/php_error_*.php日志中是否有WebpService convert failed记录
Q: 转换后图片体积反而变大了?
A: 通常发生在高质量参数 + 小尺寸图片上。建议:
降低「压缩质量」(如 80 → 70)
提高「最小文件大小」阈值(如 100KB → 200KB)
Q: 透明 PNG 转换后背景变黑了?
A: 已在插件中通过 imagealphablending(false) + imagesavealpha(true) 处理。若仍出现,检查 GD 扩展版本是否过旧。
Q: 会影响已有的旧图片吗?
A: 不会。插件仅在上传时对新图片进行转换,不会扫描和转换历史图片。
卸载
后台 → 插件管理 → 找到「WebP 压缩」→ 点击「卸载」
卸载会清理 setting 表中的 xnx_webp 配置项,已转换的 WebP 图片保留不动。
版本记录
v1.0.0 (2026-07-22):首发版本
上传图片自动转 WebP
Imagick 优先 / GD 降级
后台可配置:质量、最大宽高、GIF 处理、最小尺寸阈值
三语言支持(简中 / 繁中 / 英文)