Доброго времени суток.
Работаем на Битриксе с 2013 года. На данный момент номенклатура насчитывает около 7000 товаров.
За это время поменялось куча контент манагеров, которые занимались заполнением карточек товаров.
Делая в очередной раз бекап обнаружил, что его размер уже почти 12 Gb (учитывая что пару лет назад было 5000 товаров и размер архива был около 6 Gb)
Первая проблема - очень много "мёртвых" изображений. Т.е. тех, которые раньше были привязаны к какому либо инфоблоку (товару), впоследствии товар был удален, а файлы на сервере так и висят.
С этой проблемой боролся найденым в интернете способом:
В файл
/bitrix/php_interface/init.php в конец добавляем код:
Код |
---|
// Очистка папки /upload/iblock от ненужных изображений
function CleanUpUpload() {
global $DB;
define("NO_KEEP_STATISTIC", true);
define("NOT_CHECK_PERMISSIONS", true);
$deleteFiles = 'yes'; //Удалять ли найденые файлы yes/no
$saveBackup = 'no'; //Создаст бэкап файла yes/no
//Папка для бэкапа
$patchBackup = $_SERVER['DOCUMENT_ROOT'] . "/upload/iblock_Backup/";
//Целевая папка для поиска файлов
$rootDirPath = $_SERVER['DOCUMENT_ROOT'] . "/upload/iblock";
$time_start = microtime(true);
//Создание папки для бэкапа
if (!file_exists($patchBackup)) {
CheckDirPath($patchBackup);
}
// Получаем записи из таблицы b_file
$arFilesCache = array();
$result = $DB->Query('SEL ECT FILE_NAME, SUBDIR FR OM b_file WHERE MODULE_ID = "iblock"');
while ($row = $result->Fetch()) {
$arFilesCache[$row['FILE_NAME']] = $row['SUBDIR'];
}
$hRootDir = opendir($rootDirPath);
$count = 0;
$contDir = 0;
$countFile = 0;
$i = 1;
$removeFile=0;
while (false !== ($subDirName = readdir($hRootDir))) {
if ($subDirName == '.' || $subDirName == '..') {
continue;
}
//Счётчик пройденых файлов
$filesCount = 0;
$subDirPath = "$rootDirPath/$subDirName"; //Путь до подкатегорий с файлами
$hSubDir = opendir($subDirPath);
while (false !== ($fileName = readdir($hSubDir))) {
if ($fileName == '.' || $fileName == '..') {
continue;
}
$countFile++;
if (array_key_exists($fileName, $arFilesCache)) { //Файл с диска есть в списке файлов базы - пропуск
$filesCount++;
continue;
}
$fullPath = "$subDirPath/$fileName"; // полный путь до файла
$backTrue = false; //для создание бэкапа
if ($deleteFiles === 'yes') {
if (!file_exists($patchBackup . $subDirName)) {
if (CheckDirPath($patchBackup . $subDirName . '/')) { //создал поддиректорию
$backTrue = true;
}
} else {
$backTrue = true;
}
if ($backTrue) {
if ($saveBackup === 'yes') {
CopyDirFiles($fullPath, $patchBackup . $subDirName . '/' . $fileName); //копия в бэкап
}
}
//Удаление файла
if (unlink($fullPath)) {
$removeFile++;
}
} else {
$filesCount++;
}
$i++;
$count++;
unset($fileName, $backTrue);
}
closedir($hSubDir);
//Удалить поддиректорию, если удаление активно и счётчик файлов пустой - т.е каталог пуст
if ($deleteFiles && !$filesCount) {
rmdir($subDirPath);
}
$contDir++;
}
closedir($hRootDir);
return "CleanUpUpload();";
}
// Конец очистки
|
Затем добавляем агента с необходимой Вам периодичностью (я поставил себе 30 дней) и ждём выполнения
Изначально запускал скрипт (и Вам советую) со следующими значениями переменных:
$deleteFiles = 'yes';
$saveBackup = 'yes';
В этом случае все удаляемые файлы из папки "/upload/iblock/" помещаются в папку "/upload/iblock_Backup/" и их можно (в случае чего) восстановить.
Однако "сжатие" оказалось не сильно эффективным в моём случае. Размер папки "/upload/iblock" уменьшился с 9,33 Gb до 8,69 Gb
Просмотрев некоторые изображения (выборочно), понял что очень много файлов закачивалось вообще без сжатия:
И да, я понимаю что за это нужно надавать по голове контентщикам... Но файлы УЖЕ загружены и нужно что-то делать прямо сейчас.
Наваял скрипт, который, надеюсь, поможет и Вам. Вставлять всё в тот же
/bitrix/php_interface/init.phpКод |
---|
//Сжатие изображений
class SimpleImage {
var $image;
var $image_type;
function load($filename) {
$image_info = getimagesize($filename);
$this->image_type = $image_info[2];
if( $this->image_type == IMAGETYPE_JPEG ) {
$this->image = imagecreatefromjpeg($filename);
} elseif( $this->image_type == IMAGETYPE_GIF ) {
$this->image = imagecreatefromgif($filename);
} elseif( $this->image_type == IMAGETYPE_PNG ) {
$this->image = imagecreatefrompng($filename);
}
}
function save($filename, $compression=75, $image_type=IMAGETYPE_JPEG, $permissions=null) {
// do this or they'll all go to jpeg
$image_type=$this->image_type;
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image,$filename,$compression);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image,$filename);
} elseif( $image_type == IMAGETYPE_PNG ) {
// need this for transparent png to work
imagealphablending($this->image, false);
imagesavealpha($this->image,true);
imagepng($this->image,$filename);
}
if( $permissions != null) {
chmod($filename,$permissions);}
}
function output($image_type=IMAGETYPE_JPEG) {
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image);
}
}
function getWidth() {
return imagesx($this->image);
}
function getHeight() {
return imagesy($this->image);
}
function resizeToHeight($height) {
$ratio = $height / $this->getHeight();
$width = $this->getWidth() * $ratio;
$this->resize($width,$height);
}
function resizeToWidth($width) {
$ratio = $width / $this->getWidth();
$height = $this->getheight() * $ratio;
$this->resize($width,$height);
}
function scale($scale) {
$width = $this->getWidth() * $scale/100;
$height = $this->getheight() * $scale/100;
$this->resize($width,$height);
}
function resize($width,$height,$forcesize='n') {
/* optional. if file is smaller, do not resize. */
if ($forcesize == 'n') {
if ($width > $this->getWidth() && $height > $this->getHeight()){
$width = $this->getWidth();
$height = $this->getHeight();
}
}
$new_image = imagecreatetruecolor($width, $height);
/* Check if this image is PNG or GIF, then set if Transparent*/
if(($this->image_type == IMAGETYPE_GIF) || ($this->image_type==IMAGETYPE_PNG)){
imagealphablending($new_image, false);
imagesavealpha($new_image,true);
$transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
imagefilledrectangle($new_image, 0, 0, $width, $height, $transparent);
}
imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
$this->image = $new_image;
}
}
function compress_image($source_url, $destination_url, $width=1600, $compression=75) {
$image = new SimpleImage();
$image->load($source_url);
$image->resizeToWidth((int)$width);
$image->save($destination_url,$compression);
}
function getDirContents($dir, &$results = array()){
$files = scandir($dir);
foreach($files as $key => $value){
$path = realpath($dir.DIRECTORY_SEPARATOR.$value);
if(!is_dir($path)) {
if (in_array(mime_content_type($path), array("image/jpeg", "image/pjpeg", "image/png"))) $results[] = $path;
} else if($value != "." && $value != "..") {
getDirContents($path, $results);
//if (filetype($path) == 'file') {
//$results[] = $path;
//}
}
}
return $results;
}
function CompressImages() {
$rd = $_SERVER["DOCUMENT_ROOT"];
$files = getDirContents($rd.'/upload/iblock');
foreach ($files as $file) {
compress_image($file,$file, 1200, 75);
}
return "CompressImages();";
}
//Конец сжатия изображений
|
В функции CompressImages() в строке compress_image($file,$file, 1200, 75);
1200 - ширина изображения,
75 - процент сжатия
Создал так же с периодичностью месяц агента "CompressImages();"
Результат выполнения агента - уменьшение размера папки с 8.69 до 4.7, т.е. практически в 2 раза...
До:
После:
Остался доволен как слон.
Скрипт проверяет размер изображения. Если его ширина меньше 1200, то размер изображения не меняется.
Если больше - уменьшается до ширины 1200.
Пропорции остаются неизменными.
Обрабатываются файлы jpg и png
Прозрачность png при сжатии не теряется.
Вдруг кому пригодится...
Всем бобра!