WordPress生成缩略图优化

WordPress默认情况下会给上传的每一张图片都生成几个不同大小的缩略图,一般情况下问题不大,但是如果存在短时间上传大量图片的场景,会导致服务器整体卡顿。

这个问题也很好解决,直接将生成缩略图任务扔进队列慢慢处理就好了,毕竟加载/使用缩略图使用也不是很着急的事情,不必在上传完的时候就直接生成出来。

考虑实现一个插件,上传图片成功后将缩略图生成任务扔进任务队列,然后由队列来逐步执行。唯一的问题是WordPress原生是没有任务队列集成的,不过官方也提供了一个任务队列插件Action Scheduler,那这件事情就简单了。

1. 安装Action Scheduler

2. 关闭上传过程中的缩略图生成

翻了翻WordPress的文档,可以通过`intermediate_image_sizes_advanced`这个钩子来实现,直接返回一个空数组,上传时就不会生成缩略图了。

// 禁用默认的缩略图生成
add_filter( 'intermediate_image_sizes_advanced', function () {
    return [];
} );

3. 上传成功后,将缩略图生成任务放进任务队列。

// 添加上传后的钩子,将生成缩略图任务加入到Action Scheduler队列中
add_action('add_attachment', function ($attachment_id) {
    as_schedule_single_action(
        time(),
        'generate_thumbnails_for_attachment',
        [
            'attachment_id' => $attachment_id
        ],
        'ianzhi-thumbnail-optimise'
    );
});

4. 缩略图生成任务钩子。

// 辅助函数:获取指定尺寸的具体设置
function image_get_size($attachment_id, $size) {
    global $_wp_additional_image_sizes;

    $width = get_option("{$size}_size_w");
    $height = get_option("{$size}_size_h");
    $crop = (bool) get_option("{$size}_crop");

    if (isset($_wp_additional_image_sizes[$size])) {
        $width = $_wp_additional_image_sizes[$size]['width'];
        $height = $_wp_additional_image_sizes[$size]['height'];
        $crop = $_wp_additional_image_sizes[$size]['crop'];
    }

    return array(
        'width' => $width,
        'height' => $height,
        'crop' => $crop
    );
}

// 定义缩略图生成任务
add_action('generate_thumbnails_for_attachment', function ($attachment_id) {
    // 获取附件元数据
    $metadata = wp_get_attachment_metadata($attachment_id);
    if (!$metadata) return;

    require_once(ABSPATH . 'wp-admin/includes/image.php');

    // 获取WordPress中所有已注册的图像尺寸
    $sizes = get_intermediate_image_sizes();

    foreach ($sizes as $size) {
        // 获取每个尺寸的具体设置(宽度、高度、裁剪)
        $size_array = image_get_size($attachment_id, $size);
        if (!$size_array) continue; // 如果获取失败,跳过这个尺寸

        // 生成对应尺寸的缩略图
        $resized = image_make_intermediate_size(
            get_attached_file($attachment_id),
            $size_array['width'],
            $size_array['height'],
            $size_array['crop']
        );

        if ($resized) {
            // 将新生成的缩略图信息添加到元数据中
            $metadata['sizes'][$size] = $resized;
        }
    }

    // 更新附件的元数据
    wp_update_attachment_metadata($attachment_id, $metadata);
}, 10, 1);

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注