Проблема большой фотогалереи возникла на корпоративном портале от 1С-Битрикс. За более чем год использования ограничения на максимальный размер файла размер папки /upload/ содержащей все загруженные файлы стал более 20 GB.
Особенностью данной задачи служило, то что заранее неизвестны пути к изображениям фотогалереи. Ниже приведено решение, которое будет работать на всех проектах вне зависимости от системы управления контентом.
Скрипт делает следующее:
1) Рекурсивно обходит все файлы в директории из которой запущен;
2) Если файл имеет расширение gif, png или jpeg, размер более 500 Kb, высоту более 850px и ширину более 640 px сжимает его пропорционально до этих параметров.
Требования:
1) На сервере должна быть установлена библиотека gd для php.
2) Если файлов много, сжатие займет значительное время, поэтому придется запускать из консоли, следовательно потребуется ssh.
3) У скрипта должно быть право на изменение изображений.
Скрипт с комментариями приведен ниже:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
[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 раза!
Скачать скрипт можно здесь.