Массовое изменение формата изображений в WordPress

Категория: Решение задач | Скилл: php , sql , БД | Дата: 17.09.2019
Задача: на сайте более 1000 изображений в png формате, движок Wordpress, надо все изображения перевести в jpg и изменить расширение с png на jpg

Для начала результаты тестов: оказалось что аналогичные jpg файлы весят от 1,5 до 5 раз меньше нежели png файлы, причем без потери качества.

Обновление базы данных

Для того чтобы сделать SQL запрос, необходимо войти в веб интерфейс phpMyAdmin соответствующей базы данных, затем перейти во вкладку SQL.

Таблица wp_posts

Замена значений post_mime_type и расширения в guid (видимо ссылка на изображение) у всех постов с post_type равным attachment и post_mime_type равным image/png:

UPDATE `wp_posts` SET `post_mime_type`='image/jpg', `guid`=REPLACE(`guid`, '.png', '.jpg') WHERE `post_type`='attachment' and `post_mime_type`='image/png'

Замена во всех постах расширения в ссылках на изображения:

UPDATE 'wp_posts' SET 'post_content'=REPLACE('post_content', '.png', '.jpg') WHERE 'post_type'='post'

Таблица wp_postmeta

Замена расширения файлов в meta_value у тех строк таблицы, которые имеют meta_key равным _wp_attached_file:

UPDATE 'wp_postmeta' SET 'meta_value'=REPLACE('meta_value', '.png', '.jpg') WHERE 'meta_key'='_wp_attached_file'`

Замена расширения файлов в meta_value у тех строк таблицы, которые имеют meta_key равным _wp_attachment_metadata:

UPDATE 'wp_postmeta' SET 'meta_value'=REPLACE('meta_value', '.png', '.jpg') WHERE 'meta_key'='_wp_attachment_metadata'

Замена значения meta_value у тех строк таблицы, которые имеют meta_key равным _wp_attachment_metadata:

UPDATE 'wp_postmeta' SET 'meta_value'=REPLACE('meta_value', 'image/png', 'image/jpg') WHERE 'meta_key'='_wp_attachment_metadata'

Конвертирование файлов на сервере

Необходимо конвертировать все изображения на сервере и изменить расширения при помощи php скрипта extensionedit.php который разместим в директории wp-content:

<?php
 
set_time_limit(0);
 
//! пути относительно скрипта, откуда берем картинки
$g_aSrcPath = array(
    "uploads/2017",
    "uploads/2018"
    );
 
//! 
$g_sExtCurr = "png";
$g_sExtNew = "jpg";
 
//**************************************************************************
 
//! сканируем директорию, на выходе получаем все пути до файлов (в том числе и вложенных)
function ScanPath($dir)
{
    $d = array();
    $arr = opendir($dir);
  
    while($v = readdir($arr))
    {
        if($v == '.' or $v == '..') continue;
        if(!is_dir($dir.DIRECTORY_SEPARATOR.$v)) 
            $d[] = $v;
        if(is_dir($dir.DIRECTORY_SEPARATOR.$v)) 
        {
            $aArr = ScanPath($dir.DIRECTORY_SEPARATOR.$v);
                     
            for($i=0, $il=count($aArr); $i<$il; ++$i)
            {
                $d[] = $v.DIRECTORY_SEPARATOR.$aArr[$i];
            }
        }
    }
  
    return $d;
}
 
//! загрузка изображения, возвращает resource
function LoadImg($sPath)
{
    return imagecreatefromstring(file_get_contents($sPath));
}
 
function GetExtension($sFile) 
{
    return substr(strrchr($sFile, '.'), 1);
}
 
//**************************************************************************
 
//
if(!empty($g_sExtCurr) && !empty($g_sExtNew))
{
    $iCountEdit = 0;
     
    //проходимся по всем указанным путям, ищем изображения
    for($i=0, $il=count($g_aSrcPath); $i<$il; ++$i)
    {
        //получаем список файлов (с путями)
        $aFiles = ScanPath($g_aSrcPath[$i]);
         
        //проходимся по списку файлов
        for($k=0, $kl=count($aFiles); $k<$kl; ++$k)
        {
            if(mb_stripos($aFiles[$k], "favicon") !== false)
                continue;
             
             
            $sSrcParh = $g_aSrcPath[$i].DIRECTORY_SEPARATOR.$aFiles[$k];
             
            //echo $sSrcParh . "|" . GetExtension($sSrcParh);
             
            if(GetExtension($sSrcParh) == $g_sExtCurr)
            {
                $sFileName = basename($sSrcParh, "." . $g_sExtCurr);
                $sNewParh = dirname($sSrcParh);
                $sNewParh = $sNewParh.DIRECTORY_SEPARATOR.$sFileName.".".$g_sExtNew;
                 
                $hSrcImg = LoadImg($sSrcParh);
                rename($sSrcParh,$sNewParh);
                imagejpeg($hSrcImg, $sNewParh, 100);
                ++$iCountEdit;
            }
        }
    }
 
    echo "Edit extension " . $iCountEdit . " files";
}
else
{
    http_response_code(404);
    die;
}
?>

Запуск скрипта: my-site.ru/wp-content/extensionedit.php

Ссылки на изображения на сторонних сайтах

Будет плохо если ссылки на png файлы будут битыми, поэтому надо сделать чтобы они стали доступны, но с редиректом.

В директории wp-content необходимо создать 2 файла.

.htaccess:

AddDefaultCharset utf-8
 
<IfModule mod_rewrite.c>
RewriteEngine On
Options +FollowSymlinks
RewriteBase /
  
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /wp-content/uploads/oldimages.php?q=$1 [L,QSA]
</IfModule>

oldimages.php:

<?php
 
function LoadPage($sUrl)
{   
    $sHeaders = array(
        "User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0",
    ); 
     
    $hCurl = curl_init();
    curl_setopt($hCurl, CURLOPT_URL, $sUrl);
     
    curl_setopt($hCurl, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($hCurl, CURLOPT_SSL_VERIFYPEER, 0);
     
    curl_setopt($hCurl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($hCurl, CURLOPT_TIMEOUT, 60);
    curl_setopt($hCurl, CURLOPT_HTTPHEADER, $sHeaders); 
     
    $result = curl_exec($hCurl);
    $info = curl_getinfo($hCurl);
     
    $tries = 0;
    while(curl_errno($hCurl) != 0 && $tries++ < 10)
    {
        $result = curl_exec($hCurl);
        $info = curl_getinfo($hCurl);
        sleep(1);
    }
  
    curl_close($hCurl);
    return($result); 
} 
 
//**************************************************************************
 
$sQuery = $_GET['q']; 
$sFileName = basename($sQuery, ".png"); 
$sNewPath = dirname($sQuery); 
$sNewPath = $sNewPath.DIRECTORY_SEPARATOR.$sFileName.".jpg"; 
if(!is_file($sNewPath)) 
{ 
    http_response_code(404); 
    echo LoadPage("https://film4life.ru/404"); 
    die; 
} 
 
header("Location: " . $sFileName.".jpg", true, 301); 
die; 
?>

Вкратце:

  • в случае отсутсвия файла, направляем запрос на скрипт oldomages.php
  • если скрипт находит аналогичное изображение с png расширением, то редиректит на него, иначе загружает 404 страницу и показывает ее пользователю, отправляя при этом код ошибки.
Update. Выяснилось что можно сделать все намного проще, для этого в файл .htaccess нужно добавить (перед всеми правилами):

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(wp\-content/uploads/.*)\.png$ /$1.jpg [L,QSA]

Мой итоговый .htaccess:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(wp\-content/uploads/.*)\.png$ /$1.jpg [L,QSA]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
 
# END WordPress

Теперь все изображения доступны и по адресу с png расширение, однако с редиректом.

Итог

  • Размер до конвертирования: 1,64 гб.
  • Размер после конвертирования: 926 мб.
  • Экономия места: 753 мб.
  • Коэффициент сжатия: 1,81.
Я Виталий, ник в сети Byurrer.
Увлекаюсь программированием, веду интересные проекты, пишу здесь об интересующих меня вещах: о работе, проектах, увлечениях и проффесиональном развитии.
Мое резюме

Проекты
SkyXEngine, PHP-API, S4G
Категории
В разработке :)
Популярное
В разработке :)