xnx_webp — WebP 压缩
> Xiuno X 插件:上传图片时自动转换为 WebP 格式,显著减小图片体积,提升页面加载速度。
功能特性
- 自动转换:用户上传图片时自动转换为 WebP 格式,无需手动操作
- 双引擎支持:优先使用 Imagick(质量更好),降级使用 PHP GD 扩展
- 等比例缩放:超过最大宽高时按比例缩放,不拉伸变形
- 透明通道保留:PNG / GIF / BMP 转换后保留透明背景
- 智能跳过:
- 文件小于阈值(默认 100KB)时跳过 - GIF 动图默认跳过(可配置开启) - 已是 WebP 格式跳过
- 失败降级:转换失败时记录日志并使用原图,不中断上传流程
- 全局覆盖:覆盖所有走
attach-create路由的上传场景(发帖、回帖、编辑器插图、应用中心截图等)
环境要求
- Xiuno X(BBS 1.0+)
- PHP 7.0+(推荐 PHP 8.0+)
- 至少安装以下任一扩展:
- 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 | 后台设置页显示红色警告,上传流程使用原图 | | 单次转换失败 | 记录 xn_log 日志(php_error 通道),使用原图 | | 图片损坏无法读取 | getimagesize() 返回 false,跳过转换 | | 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 imagick - GD 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):首发版本
- Imagick 优先 / GD 降级 - 后台可配置:质量、最大宽高、GIF 处理、最小尺寸阈值 - 三语言支持(简中 / 繁中 / 英文)
许可证
随 Xiuno X 主项目分发。
版本 1.0.0 | 兼容 Xiuno 1.1+
版本:v1.0.0
适用版本:1.1
开发者:Twelve

