WordPress 实现批量将媒体库里图片转换成WebP格式代码版

我非常理解你想用纯代码来解决这个问题的心情。 本身就是一个追求极致轻量化的,少装一个插件,网站的运行负担就少一分。

用纯 PHP 代码“批量”转换媒体库中现有的图片,风险极高,通常不建议自己手写。

为什么纯代码批量转换存量图片是个“坑”?

  1. 服务器超时 (504 Gateway Timeout): 图像处理非常消耗 CPU 和内存。如果你有几百上千张图片,一个简单的 PHP 循环绝对会导致服务器资源耗尽并强制中断。
  2. 数据库关联断裂:WordPress 不仅仅是在硬盘上存了一张图。它在数据库里记录了原图路径、缩略图元数据(Meta Data),并且在你的文章内容(Post Content)里硬编码了 。如果你只改了文件,网站上的图片会全部裂开。<img src="...jpg">

不过,既然你希望走代码流,这里有一个折中且最稳妥的纯代码方案:分为“拦截新图片”和“处理老图片”两步走。

第一步:纯代码实现“新上传图片”自动转 WebP

你可以将以下代码添加到 主题的functions.php 中。这段代码会在你未来上传 JPG/PNG 时,利用 WordPress 自带的 自动将其转换为 WebP,并替换掉原图。functions.php WP_Image_Editor

/**
 * 上传图片时自动转换为 WebP 格式
 */
add_filter( 'wp_handle_upload', 'arkhe_auto_convert_to_webp' );

function arkhe_auto_convert_to_webp( $upload ) {
    // 只处理 JPG 和 PNG
    if ( $upload['type'] == 'image/jpeg' || $upload['type'] == 'image/png' ) {
        $file_path = $upload['file'];
        
        // 调用 WordPress 内置的图像编辑器 (依赖 GD 库或 Imagick)
        $image_editor = wp_get_image_editor( $file_path );
        
        if ( ! is_wp_error( $image_editor ) ) {
            // 生成新的 WebP 文件路径
            $webp_file = preg_replace( '/\.(jpg|jpeg|png)$/i', '.webp', $file_path );
            
            // 保存为 WebP 格式
            $saved = $image_editor->save( $webp_file, 'image/webp' );
            
            if ( ! is_wp_error( $saved ) ) {
                // 转换成功后,删除原 JPG/PNG 文件
                @unlink( $file_path ); 
                
                // 更新 WordPress 的上传信息
                $upload['file'] = $webp_file;
                $upload['url']  = preg_replace( '/\.(jpg|jpeg|png)$/i', '.webp', $upload['url'] );
                $upload['type'] = 'image/webp';
            }
        }
    }
    return $upload;
}

优点: 零插件,不增加前端负担,未来上传的图片永远是 WebP格式,vps流量既节省,又加速网站打开速度,体验感一举两得。

第二步:处理“现存的老图片”(WP-CLI 方案)

对于媒体库里已经存在的老图片,不要用普通的 PHP 脚本。如果你懂一点服务器操作(SSH),行业标准做法是使用 WP-CLI(WordPress 命令行工具) 配合第三方包来处理,这样不会受限于 PHP 超时时间。

你可以使用 结合社区提供的 WebP 转换脚本,或者最安全的做法是:用代码生成 WebP 副本,但不修改数据库,通过 Nginx/Apache 规则让浏览器自动读取 WebP。wp-cli/media-command

Nginx 伪静态判断方案(服务器端无缝替换)

如果你将老图片通过本地工具(如 XnConvert)批量转换为 WebP,上传回 目录(保持文件名一致,仅后缀不同,例如 旁边多一个 )。wp-content/uploads/image.jpgimage.jpg.webp

然后在服务器的 Nginx 配置文件中添加以下规则:

# 检查浏览器是否支持 WebP,并且服务器上存在对应的 WebP 文件
location ~* ^/wp-content/uploads/(.+/)*(.+)\.(png|jpe?g)$ {
    add_header Vary Accept;
    if ($http_accept !~* "webp"){
        break;
    }
    try_files $uri.webp $uri =404;
}

为什么这是神级操作?

绝对安全: 你完全不需要修改 WordPress 数据库里的文章内容。

兼容性满分: 支持 WebP 的浏览器(Chrome)会下载 WebP,老旧浏览器(IE)会继续下载原版 JPG,完美解决兼容问题。

直接在服务器底层跑命令行不仅效率极高,还能完美避开 PHP 超时的限制。配合 Nginx 的底层分发,这套方案堪称服务器运维级的最佳实践。

先用 Linux 命令批量生成 WebP 副本再用 Nginx 规则实现无缝替换

第一步:使用 Linux 命令行批量生成 WebP

我们需要用到一个极其轻量的官方工具 cwebp。它非常稳定,资源占用也完全可控。

1. 安装 WebP 转换工具 通过 SSH 登录你的服务器,根据你的操作系统运行以下命令安装环境:

  • Ubuntu/Debian: sudo apt-get install webp
  • CentOS/RHEL: sudo yum install libwebp-tools

2. 执行批量转换脚本 进入你的 WordPress 网站图片上传目录。通常路径如下(请根据你的实际路径修改):

cd /你的网站根目录/wp-content/uploads/

进入目录后,直接复制并运行下面这段复合命令。它的逻辑是:递归查找所有 JPG/PNG 图片 -> 检查是否已有 WebP 副本 -> 如果没有,则以 80% 的质量生成一个同名的 .webp 副本。

find . -type f -and \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \) -exec bash -c '
  webp_path="$0.webp"
  if [ ! -f "$webp_path" ]; then
    echo "正在转换: $0"
    cwebp -q 80 "$0" -o "$webp_path" -quiet
  fi
' {} \;

提示:80% 是 WebP 的黄金质量点,能在肉眼看不出画质损失的前提下,把体积压缩 40% – 70%。这个脚本自带跳过机制,以后即便重复运行,也不会对已转换的图片进行二次处理。

第二步:配置 Nginx 实现“偷天换日”

现在硬盘上已经有了形如 image.jpgimage.jpg.webp 两个文件并存的情况。接下来我们要告诉 Nginx:如果访客的浏览器支持 WebP,就悄悄把 .webp 文件塞给他,但网址依然显示为 .jpg

打开你网站的 Nginx 配置文件(如果你用的是宝塔面板,直接在“网站 – 设置 – 伪静态”或“配置文件”里修改)。在 server { ... } 块中,加入以下路由规则:

# 拦截 wp-content/uploads 下的图片请求
location ~* ^/wp-content/uploads/(.+/)*(.+)\.(png|jpe?g)$ {
    # 告诉 CDN 或浏览器端缓存,这取决于请求头中的 Accept 字段
    add_header Vary Accept;
    
    # 默认后缀为空
    set $ext "";
    
    # 检查浏览器发送的请求头中是否包含 webp 支持
    if ($http_accept ~* "webp") {
        set $ext ".webp";
    }
    
    # 核心逻辑:
    # 1. 尝试找带有 .webp 后缀的文件 ($uri$ext)
    # 2. 如果没找到,就给原图 ($uri)
    # 3. 如果连原图都没了,报 404
    try_files $uri$ext $uri =404;
}

配置完成后,记得重载 Nginx 让规则生效:

nginx -t && nginx -s reload

如何验证是否成功?

  1. 用 Chrome 浏览器打开你的一篇 Arkhe 博客文章。
  2. 按下 F12 打开开发者工具,切换到 Network (网络) 面板。
  3. 刷新页面,在列表中找到你的图片请求。
  4. 点开图片详情,查看 Response Headers (响应头)。如果看到 Content-Type: image/webp,说明 Nginx 已经成功实现了偷天换日,即使图片的 URL 后缀依然是 .jpg

在跑批量转换命令之前,建议先进入一个只有几张图片的子月份文件夹(比如 wp-content/uploads/2026/02/)里测试一下效果。