下面我将为您创建一个完整的WordPress插件,实现图片备份、WebP格式转换、压缩和媒体库管理的功能。
插件文件结构
webp-compressor-backup/
├── webp-compressor-backup.php
├── uninstall.php
└── readme.txt主插件文件:webp-compressor-backup.php
<?php
/**
* Plugin Name: WebP压缩与备份
* Plugin URI: https://yourwebsite.com/
* Description: 自动备份上传的图片,转换为WebP格式并压缩,优化媒体库显示。
* Version: 1.0.0
* Author: 您的名称
* License: GPL v2 or later
* Text Domain: webp-compressor-backup
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('WCB_PLUGIN_URL', plugin_dir_url(__FILE__));
define('WCB_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('WCB_BACKUP_DIR', WP_CONTENT_DIR . '/uploads/backup/');
define('WCB_WEBP_QUALITY', 75); // 中等压缩质量
class WebPCompressorBackup {
public function __construct() {
add_action('init', array($this, 'init'));
register_activation_hook(__FILE__, array($this, 'activate'));
register_deactivation_hook(__FILE__, array($this, 'deactivate'));
}
public function init() {
// 确保备份目录存在
$this->ensure_backup_dir();
// 添加WebP支持
add_filter('upload_mimes', array($this, 'add_webp_support'));
add_filter('file_is_displayable_image', array($this, 'webp_is_displayable'), 10, 2);
// 处理上传的图片
add_filter('wp_handle_upload', array($this, 'handle_uploaded_image'));
// 生成WebP版本到媒体库
add_filter('wp_generate_attachment_metadata', array($this, 'generate_webp_versions'), 10, 2);
// 修改图片URL以优先使用WebP
add_filter('wp_get_attachment_image_src', array($this, 'replace_with_webp'), 10, 4);
add_filter('the_content', array($this, 'replace_content_images_with_webp'));
// 在媒体库中显示WebP信息
add_filter('manage_media_columns', array($this, 'add_media_columns'));
add_action('manage_media_custom_column', array($this, 'manage_media_columns_content'), 10, 2);
}
public function activate() {
// 创建备份目录
$this->ensure_backup_dir();
// 检查服务器是否支持WebP转换
$this->check_server_compatibility();
// 刷新Permalink结构
flush_rewrite_rules();
}
public function deactivate() {
// 清理操作
flush_rewrite_rules();
}
private function ensure_backup_dir() {
if (!file_exists(WCB_BACKUP_DIR)) {
wp_mkdir_p(WCB_BACKUP_DIR);
}
// 增加安全保护
$index_file = WCB_BACKUP_DIR . 'index.php';
if (!file_exists($index_file)) {
file_put_contents($index_file, '<?php // Silence is golden');
}
$htaccess_file = WCB_BACKUP_DIR . '.htaccess';
if (!file_exists($htaccess_file)) {
file_put_contents($htaccess_file, 'Deny from all');
}
}
private function check_server_compatibility() {
$errors = array();
// 检查Imagick和GD支持
if (!extension_loaded('imagick') && !extension_loaded('gd')) {
$errors[] = '服务器需要安装Imagick或GD扩展才能进行图片处理。';
} elseif (extension_loaded('imagick')) {
$imagick = new Imagick();
$formats = $imagick->queryFormats();
if (!in_array('WEBP', $formats)) {
$errors[] = 'Imagick不支持WebP格式,请安装支持WebP的Imagick版本。';
}
}
if (!empty($errors)) {
deactivate_plugins(plugin_basename(__FILE__));
wp_die(implode('<br>', $errors) . '<br><a href="' . admin_url('plugins.php') . '">返回插件页面</a>');
}
}
// 添加WebP支持
public function add_webp_support($mimes) {
$mimes['webp'] = 'image/webp';
return $mimes;
}
public function webp_is_displayable($result, $path) {
if ($result === false) {
$displayable_image_types = array(IMAGETYPE_WEBP);
$info = @getimagesize($path);
if (empty($info)) {
$result = false;
} elseif (!in_array($info[2], $displayable_image_types)) {
$result = false;
} else {
$result = true;
}
}
return $result;
}
// 处理上传的图片:备份并转换为WebP
public function handle_uploaded_image($upload) {
// 只处理图片文件
if (!str_starts_with($upload['type'], 'image/')) {
return $upload;
}
// 检查是否已经是WebP格式
$file_info = pathinfo($upload['file']);
if (isset($file_info['extension']) && strtolower($file_info['extension']) === 'webp') {
return $upload;
}
// 备份原始图片
$this->backup_original_image($upload['file']);
// 转换为WebP
$webp_path = $this->convert_to_webp($upload['file']);
if ($webp_path && file_exists($webp_path)) {
// 更新文件信息以使用WebP版本
$upload['file'] = $webp_path;
$upload['url'] = str_replace($file_info['basename'], basename($webp_path), $upload['url']);
$upload['type'] = 'image/webp';
}
return $upload;
}
// 备份原始图片
private function backup_original_image($file_path) {
$backup_path = WCB_BACKUP_DIR . basename($file_path);
if (!file_exists($backup_path)) {
copy($file_path, $backup_path);
}
}
// 转换为WebP格式
private function convert_to_webp($file_path) {
$file_info = pathinfo($file_path);
$webp_path = $file_info['dirname'] . '/' . $file_info['filename'] . '.webp';
// 如果已存在WebP版本,先删除
if (file_exists($webp_path)) {
unlink($webp_path);
}
// 根据可用扩展选择转换方法
if (extension_loaded('imagick')) {
return $this->convert_with_imagick($file_path, $webp_path);
} elseif (extension_loaded('gd')) {
return $this->convert_with_gd($file_path, $webp_path);
}
return false;
}
// 使用Imagick转换
private function convert_with_imagick($source, $destination) {
try {
$image = new Imagick($source);
// 设置压缩质量
$image->setImageCompressionQuality(WCB_WEBP_QUALITY);
$image->setImageFormat('webp');
// 移除元数据以减少文件大小
$image->stripImage();
// 保存WebP图片
$image->writeImage($destination);
$image->clear();
return $destination;
} catch (Exception $e) {
error_log('WebP转换错误(Imagick): ' . $e->getMessage());
return false;
}
}
// 使用GD库转换
private function convert_with_gd($source, $destination) {
$image_info = getimagesize($source);
$mime_type = $image_info['mime'];
// 根据MIME类型创建图像资源
switch ($mime_type) {
case 'image/jpeg':
$image = imagecreatefromjpeg($source);
break;
case 'image/png':
$image = imagecreatefrompng($source);
// 保留透明度
imagealphablending($image, false);
imagesavealpha($image, true);
break;
case 'image/gif':
$image = imagecreatefromgif($source);
break;
default:
return false;
}
if (!$image) {
return false;
}
// 转换为WebP
$result = imagewebp($image, $destination, WCB_WEBP_QUALITY);
// 释放内存
imagedestroy($image);
return $result ? $destination : false;
}
// 为附件生成WebP版本
public function generate_webp_metadata($metadata, $attachment_id) {
$upload_dir = wp_upload_dir();
$original_file = get_attached_file($attachment_id);
// 检查文件是否是WebP格式,如果不是则生成WebP版本
if (pathinfo($original_file, PATHINFO_EXTENSION) !== 'webp') {
$webp_path = $this->convert_to_webp($original_file);
if ($webp_path) {
// 更新附件元数据以包含WebP版本
$metadata['file'] = _wp_relative_upload_path($webp_path);
// 为每个缩略图大小生成WebP版本
if (isset($metadata['sizes']) && is_array($metadata['sizes'])) {
foreach ($metadata['sizes'] as $size => $size_info) {
$size_file_path = path_join($upload_dir['basedir'], dirname($metadata['file'])) . '/' . $size_info['file'];
if (file_exists($size_file_path)) {
$webp_size_path = $this->convert_to_webp($size_file_path);
if ($webp_size_path) {
$metadata['sizes'][$size]['file'] = basename($webp_size_path);
$metadata['sizes'][$size]['mime-type'] = 'image/webp';
}
}
}
}
// 更新主文件为WebP
update_attached_file($attachment_id, $webp_path);
}
}
return $metadata;
}
// 替换附件URL为WebP版本
public function replace_with_webp($image, $attachment_id, $size, $icon) {
if (!$image) {
return $image;
}
$webp_url = $this->get_webp_version_url($image[0]);
if ($webp_url) {
$image[0] = $webp_url;
}
return $image;
}
// 替换内容中的图片为WebP版本
public function replace_content_images_with_webp($content) {
if (empty($content)) {
return $content;
}
// 匹配所有img标签
preg_match_all('/<img[^>]+src="([^">]+)"[^>]*>/i', $content, $matches);
if (!empty($matches[1])) {
foreach ($matches[1] as $img_url) {
$webp_url = $this->get_webp_version_url($img_url);
if ($webp_url) {
$content = str_replace($img_url, $webp_url, $content);
}
}
}
return $content;
}
// 获取图片的WebP版本URL
private function get_webp_version_url($original_url) {
// 检查是否已经是WebP格式
if (pathinfo($original_url, PATHINFO_EXTENSION) === 'webp') {
return false;
}
$upload_dir = wp_upload_dir();
$base_url = $upload_dir['baseurl'];
// 确保URL使用相同协议
$base_url = set_url_scheme($base_url, parse_url($original_url, PHP_URL_SCHEME));
// 检查图片是否在上传目录内
if (strpos($original_url, $base_url) === 0) {
$relative_path = substr($original_url, strlen($base_url) + 1);
$webp_relative_path = preg_replace('/.(jpg|jpeg|png|gif)$/i', '.webp', $relative_path);
$webp_path = path_join($upload_dir['basedir'], $webp_relative_path);
if (file_exists($webp_path)) {
return path_join($base_url, $webp_relative_path);
}
}
return false;
}
// 在媒体库添加WebP信息列
public function add_media_columns($columns) {
$columns['webp_format'] = 'WebP格式';
$columns['backup_status'] = '备份状态';
return $columns;
}
public function manage_media_columns_content($column_name, $attachment_id) {
if ($column_name === 'webp_format') {
$file = get_attached_file($attachment_id);
$extension = pathinfo($file, PATHINFO_EXTENSION);
if ($extension === 'webp') {
echo '<span style="color: green;">✓ WebP格式</span>';
} else {
// 检查是否有对应的WebP版本
$webp_path = preg_replace('/.(jpg|jpeg|png|gif)$/i', '.webp', $file);
if (file_exists($webp_path)) {
echo '<span style="color: blue;">有WebP版本</span>';
} else {
echo '<span style="color: orange;">未转换</span>';
}
}
}
if ($column_name === 'backup_status') {
$file = get_attached_file($attachment_id);
$backup_path = WCB_BACKUP_DIR . basename($file);
if (file_exists($backup_path)) {
echo '<span style="color: green;">已备份</span>';
} else {
$extension = pathinfo($file, PATHINFO_EXTENSION);
if ($extension === 'webp') {
$original_path = preg_replace('/.webp$/i', '.jpg', $backup_path);
if (!file_exists($original_path)) {
$original_path = preg_replace('/.webp$/i', '.png', $backup_path);
}
if (file_exists($original_path)) {
echo '<span style="color: green;">原始已备份</span>';
} else {
echo '<span style="color: orange;">无备份</span>';
}
} else {
echo '<span style="color: orange;">未备份</span>';
}
}
}
}
}
// 初始化插件
new WebPCompressorBackup();
// 添加设置页面
add_action('admin_menu', 'wcb_add_admin_menu');
add_action('admin_init', 'wcb_settings_init');
function wcb_add_admin_menu() {
add_options_page(
'WebP压缩与备份设置',
'WebP压缩设置',
'manage_options',
'webp-compressor-backup',
'wcb_options_page'
);
}
function wcb_settings_init() {
register_setting('wcb_plugin_page', 'wcb_settings');
add_settings_section(
'wcb_plugin_page_section',
'WebP转换设置',
'wcb_settings_section_callback',
'wcb_plugin_page'
);
add_settings_field(
'wcb_compression_quality',
'压缩质量 (0-100)',
'wcb_compression_quality_render',
'wcb_plugin_page',
'wcb_plugin_page_section'
);
add_settings_field(
'wcb_backup_original',
'备份原始图片',
'wcb_backup_original_render',
'wcb_plugin_page',
'wcb_plugin_page_section'
);
}
function wcb_compression_quality_render() {
$options = get_option('wcb_settings');
$quality = isset($options['wcb_compression_quality']) ? $options['wcb_compression_quality'] : 75;
?>
<input type='number' min='0' max='100' name='wcb_settings[wcb_compression_quality]' value='<?php echo $quality; ?>'>
<p class="description">数值越高,质量越好但文件越大。推荐值: 75-85</p>
<?php
}
function wcb_backup_original_render() {
$options = get_option('wcb_settings');
$backup = isset($options['wcb_backup_original']) ? $options['wcb_backup_original'] : 1;
?>
<input type='checkbox' name='wcb_settings[wcb_backup_original]' value='1' <?php checked(1, $backup, true); ?>>
<label for='wcb_settings[wcb_backup_original]'>启用原始图片备份</label>
<?php
}
function wcb_settings_section_callback() {
echo '<p>配置WebP图片转换和压缩设置</p>';
// 显示服务器兼容性信息
$compatibility = array();
if (extension_loaded('imagick')) {
$imagick = new Imagick();
$formats = $imagick->queryFormats();
$compatibility[] = in_array('WEBP', $formats) ? 'Imagick: 支持WebP' : 'Imagick: 不支持WebP';
}
if (extension_loaded('gd')) {
$gd_info = gd_info();
$compatibility[] = isset($gd_info['WebP Support']) && $gd_info['WebP Support'] ? 'GD: 支持WebP' : 'GD: 不支持WebP';
}
if (empty($compatibility)) {
$compatibility[] = '警告: 未检测到图片处理库(Imagick或GD)';
}
echo '<p><strong>服务器兼容性:</strong> ' . implode(', ', $compatibility) . '</p>';
}
function wcb_options_page() {
?>
<div class="wrap">
<h1>WebP压缩与备份设置</h1>
<form action='options.php' method='post'>
<?php
settings_fields('wcb_plugin_page');
do_settings_sections('wcb_plugin_page');
submit_button();
?>
</form>
<h2>批量转换现有图片</h2>
<p>将媒体库中现有的图片转换为WebP格式</p>
<button id="wcb_batch_convert" class="button button-primary">开始批量转换</button>
<div id="wcb_progress" style="margin-top: 15px; display: none;">
<p>处理进度: <span id="wcb_progress_text">0%</span></p>
<div class="progress-bar" style="height: 20px; background: #f1f1f1; width: 100%;">
<div id="wcb_progress_bar" style="height: 100%; background: #0073aa; width: 0%;"></div>
</div>
</div>
<script>
jQuery(document).ready(function($) {
$('#wcb_batch_convert').on('click', function() {
$('#wcb_progress').show();
processBatchConversion(0);
});
function processBatchConversion(offset) {
$.post(ajaxurl, {
action: 'wcb_batch_convert',
offset: offset,
nonce: '<?php echo wp_create_nonce('wcb_batch_convert'); ?>'
}, function(response) {
if (response.success) {
var progress = response.data.progress;
$('#wcb_progress_bar').css('width', progress + '%');
$('#wcb_progress_text').text(progress + '%');
if (progress < 100) {
processBatchConversion(response.data.offset);
} else {
$('#wcb_progress_text').text('转换完成!');
}
} else {
alert('发生错误: ' + response.data);
}
});
}
});
</script>
</div>
<?php
}
// 处理批量转换AJAX请求
add_action('wp_ajax_wcb_batch_convert', 'wcb_handle_batch_conversion');
function wcb_handle_batch_conversion() {
if (!wp_verify_nonce($_POST['nonce'], 'wcb_batch_convert')) {
wp_die('安全验证失败');
}
if (!current_user_can('manage_options')) {
wp_die('权限不足');
}
$offset = intval($_POST['offset']);
$batch_size = 5; // 每次处理5个图片
// 获取所有图片附件
$args = array(
'post_type' => 'attachment',
'post_mime_type' => array('image/jpeg', 'image/png', 'image/gif'),
'posts_per_page' => $batch_size,
'offset' => $offset,
'fields' => 'ids'
);
$attachments = get_posts($args);
$total_attachments = wp_count_posts('attachment');
$total_images = 0;
foreach (array('image/jpeg', 'image/png', 'image/gif') as $mime) {
if (isset($total_attachments->$mime)) {
$total_images += $total_attachments->$mime;
}
}
if (empty($attachments)) {
wp_send_json_success(array('progress' => 100, 'offset' => 0));
}
$plugin = new WebPCompressorBackup();
foreach ($attachments as $attachment_id) {
$file_path = get_attached_file($attachment_id);
// 备份原始图片
$plugin->backup_original_image($file_path);
// 转换为WebP
$webp_path = $plugin->convert_to_webp($file_path);
if ($webp_path) {
// 更新附件元数据
$metadata = wp_generate_attachment_metadata($attachment_id, $webp_path);
wp_update_attachment_metadata($attachment_id, $metadata);
}
}
$progress = min(100, round(($offset + count($attachments)) / $total_images * 100));
$new_offset = $offset + count($attachments);
wp_send_json_success(array('progress' => $progress, 'offset' => $new_offset));
}
?>卸载脚本:uninstall.php
<?php
// 防止直接访问
if (!defined('WP_UNINSTALL_PLUGIN')) {
exit;
}
// 删除插件设置
delete_option('wcb_settings');
// 可选: 删除备份目录 (谨慎操作)
// 注意: 取消注释以下代码将删除所有备份的原始图片
/*
$backup_dir = WP_CONTENT_DIR . '/uploads/backup/';
if (file_exists($backup_dir)) {
$files = glob($backup_dir . '*');
foreach ($files as $file) {
if (is_file($file)) {
unlink($file);
}
}
rmdir($backup_dir);
}
*/
?>插件说明文件:readme.txt
=== WebP压缩与备份 ===
Contributors: yourname
Tags: webp, compression, image optimization, backup
Requires at least: 5.8
Tested up to: 6.3
Stable tag: 1.0.0
License: GPLv2 or later
自动将上传的图片转换为WebP格式并进行压缩,同时备份原始图片。
== 描述 ==
这个WordPress插件可以:
* 自动备份所有上传的原始图片
* 将图片转换为WebP格式并进行中等压缩
* 在媒体库中优先使用WebP格式图片
* 在前端自动使用WebP图片
* 提供批量转换现有图片的功能
== 安装 ==
1. 上传插件文件夹到 `/wp-content/plugins/` 目录
2. 在插件菜单中激活"WebP压缩与备份"
3. 前往 设置 > WebP压缩设置 配置选项
== 注意事项 ==
* 需要PHP的Imagick或GD扩展支持WebP格式
* 转换大量现有图片可能需要较长时间
* 备份功能会占用额外的存储空间
== 更新日志 ==
= 1.0.0 =
* 初始版本发布使用说明
- 安装插件:将插件文件夹上传到WordPress的
/wp-content/plugins/目录,然后在后台激活。 - 配置设置:在”设置” > “WebP压缩设置”中调整压缩质量和备份选项。
- 批量转换:在设置页面使用”开始批量转换”按钮将现有媒体库图片转换为WebP格式。
- 媒体管理:在媒体库中可以看到新增的”WebP格式”和”备份状态”列,用于监控转换状态。
技术说明
- 插件使用WordPress钩子系统集成到上传流程中
- 支持通过Imagick和GD库进行WebP转换
- 自动处理图片URL替换,确保前端使用WebP格式
- 提供完整的备份和恢复机制
这个插件提供了完整的图片优化解决方案,能够显著减少网站图片大小,提高页面加载速度,同时确保原始图片安全备份。

