Проблема большой фотогалереи возникла на корпоративном портале от 1С-Битрикс. За более чем год использования ограничения на максимальный размер файла размер папки /upload/ содержащей все загруженные файлы стал более 20 GB.
Особенностью данной задачи служило, то что заранее неизвестны пути к изображениям фотогалереи. Ниже приведено решение, которое будет работать на всех проектах вне зависимости от системы управления контентом.
Скрипт делает следующее:
1) Рекурсивно обходит все файлы в директории из которой запущен;
2) Если файл имеет расширение gif, png или jpeg, размер более 500 Kb, высоту более 850px и ширину более 640 px сжимает его пропорционально до этих параметров.
Требования:
1) На сервере должна быть установлена библиотека gd для php.
2) Если файлов много, сжатие займет значительное время, поэтому придется запускать из консоли, следовательно потребуется ssh.
3) У скрипта должно быть право на изменение изображений.
Скрипт с комментариями приведен ниже:
[sourcecode lang="php"] #!/usr/local/bin/php #!/usr/local/bin/php // settings global $result_width, $result_height, $max_size, $resized_files; $result_width=850; // ширина изображения $result_height=640; // высота изображения $max_size=500000; // минимальный размер //settings function img_resize($src, $out, $width, $height, $color = 0xFFFFFF, $quality = 100) { global $result_width, $result_height, $max_size, $resized_files; if ((strpos(strtolower($src), '.jpg')!==false)||(strpos(strtolower($src), '.gif')!==false)||(strpos(strtolower($src), '.png')!==false)){ // Если файл не существует if (!file_exists($src)) { return false; } // Получаем массив с информацией о размере и формате картинки (mime) $size = getimagesize($src); // Исходя из формата (mime) картинки, узнаем с каким форматом имеем дело $format = strtolower(substr($size['mime'], strpos($size['mime'], '/') + 1)); //и какую функцию использовать для ее создания $picfunc = 'imagecreatefrom'.$format; if (($size>$max_size)&&($size[0]<$width)&&($size[1]>height)){ $resized_files++; // Вычилсить горизонтальное соотношение $gor = $width / $size[0]; // Вертикальное соотношение $ver = $height / $size[1]; // Если не задана высота, вычислить изходя из ширины, пропорционально if ($height == 0) { $ver = $gor; $height = $ver * $size[1]; } // Так же если не задана ширина elseif ($width == 0) { $gor = $ver; $width = $gor * $size[0]; } // Формируем размер изображения $ratio = min($gor, $ver); // Нужно ли пропорциональное преобразование if ($gor == $ratio) $use_gor = true; else $use_gor = false; $new_width = $use_gor ? $width : floor($size[0] * $ratio); $new_height = !$use_gor ? $height : floor($size[1] * $ratio); $new_left = $use_gor ? 0 : floor(($width - $new_width) / 2); $new_top = !$use_gor ? 0 : floor(($height - $new_height) / 2); $picsrc = $picfunc($src); // Создание изображения в памяти $picout = imagecreatetruecolor($width, $height); // Заполнение цветом imagefill($picout, 0, 0, $color); // Нанесение старого на новое imagecopyresampled($picout, $picsrc, $new_left, $new_top, 0, 0, $new_width, $new_height, $size[0], $size[1]); // Создание файла изображения imagejpeg($picout, $out, $quality); // Очистка памяти imagedestroy($picsrc); imagedestroy($picout); return true; } else { return false; } } else { return false; } } function scan_dir($dirname) { // Объявляем переменные замены глобальными global $count_files; global $result_width, $result_height, $max_size, $resized_files; // Открываем текущую директорию $dir = opendir($dirname); // Читаем в цикле директорию while (($file = readdir($dir)) !== false) { // Если файл обрабатываем его содержимое if($file != '.' && $file != '..') { // Если имеем дело с файлом - производим в нём замену if(is_file($dirname.'/'.$file)) { $str = $_SERVER['DOCUMENT_ROOT'].$_SERVER["REQUEST_URI"].$dirname."/".$file; $str = str_replace("//", "/", $str); $str = str_replace("./", "", $str); $str = str_replace("//", "/", $str); echo("Try to resize file # ".$count_files." \n "); img_resize($str, $str, $result_width, $result_height); // echo($_SERVER["DOCUMENT_ROOT"].$_SERVER["REQUEST_URI"].$dirname.""); $count_files++; } // Если перед нами директория, вызываем рекурсивно // функцию scan_dir if(is_dir($dirname."/".$file)) { scan_dir($dirname."/".$file); } } } // Закрываем директорию closedir($dir); } $time1 = time(); $dirname = "./"; // Текущая директория scan_dir($dirname); // Вызов рекурсивной функции echo "All files: $count_files \n "; echo "Resized files: $resized_files \n "; $time2 = time(); echo("Total time:".($time2-$time1)." sec \n"); ?> [/sourcecode]
Результат работы оказался таким: скрипт работал чуть более 4х часов, изменил чуть более
20 000 изображений. Размер папки /upload/ стал 5 Gb, т.е. уменьшился в 4 раза!
Скачать скрипт можно здесь.