Отложенный ресайз облачных файлов в CFile::ResizeImageGet
Проблема/контекст
У CFile::ResizeImageGet() есть шестой параметр $bImmediate, но по коду ядра он не включает "отложенный ресайз" сам по себе. В main/classes/general/file.php метод только передает этот флаг в событие OnBeforeResizeImage, а реальная delayed-логика подключается обработчиком модуля clouds.
Это важно, потому что для локальных файлов ресайз остается синхронным, а для файлов с HANDLER_ID из облачного хранилища поведение меняется. В CCloudStorage::OnBeforeResizeImage() ядро проверяет опцию clouds.delayed_resize и при $bImmediate = false не строит миниатюру сразу, а ставит задачу в таблицу b_clouds_file_resize через ResizeImageFileDelay(). Затем CCloudStorage::OnBeforeProlog() перехватывает запрос к resize_cache, вызывает ResizeImageFileCheck() и уже после генерации перенаправляет на готовый файл в бакете.
Решение с кодом
Практическое правило простое: delayed-режим подходит для публичных списков, где допустим отдельный HTTP-запрос на первую генерацию картинки. Для AJAX-ответов, модальных превью, административных форм и мест, где URL должен вести на уже существующий файл, ставьте $bImmediate = true. Сам Bitrix следует этому же правилу: в Bitrix\Main\UI\FileInputUnclouder::exec() и шаблоне main.file.input превью строится через ResizeImageGet(..., true).
<?php
declare(strict_types=1);
/**
* Для cloud-файлов решаем, можно ли отложить генерацию.
*/
function getPreviewImage(array $file, int $width, int $height, bool $needImmediate): array
{
$result = \CFile::ResizeImageGet(
$file,
['width' => $width, 'height' => $height],
bInitSizes: true, // вернуть реальные размеры результата
bImmediate: $needImmediate
);
return is_array($result) ? $result : [];
}
$file = \CFile::GetFileArray($pictureId);
$isCloudFile = (int)($file['HANDLER_ID'] ?? 0) > 0;
// В списке товаров допускаем delayed-генерацию только для cloud-файлов.
$listImage = getPreviewImage($file, 320, 320, false);
// В AJAX-превью файл нужен сразу, иначе можно получить URL на еще не созданный объект.
$modalImage = getPreviewImage($file, 1200, 1200, $isCloudFile);
Если вы вызываете ResizeImageGet() в JSON-ответе или сразу вставляете src в интерфейс, не рассчитывайте, что delayed-режим успеет создать файл к этому же ответу. Документация показывает только прямой CFile::ResizeImage() после SaveFile(), но не объясняет этот разрыв между локальным и cloud-сценарием. Поэтому проверяйте HANDLER_ID и осознанно выбирайте режим генерации, а не передавайте шестой параметр "на всякий случай".
Есть и еще один нюанс, который виден только в исходниках clouds. Метод ResizeImageFileDelay() не ставит задачу без необходимости: если Rectangle::resize() показывает, что новое изображение не требуется и нет фильтров или watermark, delayed-сценарий не включается. А если задача уже падала, ядро пытается перезапустить ее только спустя пять минут по TIMESTAMP_X. Это означает, что delayed-режим полезен именно как фоновая оптимизация выдачи, а не как гарантия мгновенного результата при повторном запросе.
Итог
$bImmediate имеет практический смысл только в связке с облачным хранилищем и clouds.delayed_resize. Для интерактивных превью включайте немедленную генерацию, для публичных страниц можно оставлять delayed-режим.
Комментарии (0)
Пожалуйста, войдите в аккаунт, чтобы оставить комментарий
Оставить комментарийПока нет ни одного комментария. Будьте первым!
Похожие советы