Настройка массовой загрузки фотографий товаров 1С-Битрикс
Каталог 20 000 позиций, у каждой нужно заменить основное фото и добавить галерею из 5–8 снимков. Через административный интерфейс это несколько человеко-недель ручного труда. На практике задача решается за несколько часов с помощью API Битрикс и пакетной обработки.
Где хранятся фотографии в Битрикс
Файлы товарных изображений хранятся в таблице b_file. Каждый файл имеет свой ID. Инфоблок (каталог) ссылается на них через свойства:
-
PREVIEW_PICTURE— анонсовое изображение, хранится вb_iblock_element.PREVIEW_PICTURE(FK наb_file.ID) -
DETAIL_PICTURE— детальное изображение,b_iblock_element.DETAIL_PICTURE - Свойство типа «Файл/Картинка» —
b_iblock_element_property.VALUEсо ссылкой наb_file.ID
Многократные изображения (галерея) — через свойство типа «Картинка» с флагом «Множественное». Для торговых предложений — те же поля в контексте элемента торгового предложения.
Подготовка файлов
Изображения должны быть подготовлены заранее: структура директорий по артикулу, единое именование. Удобная схема:
/import/images/
sku_001/
main.jpg
2.jpg
3.jpg
sku_002/
main.jpg
Если файлы приходят из 1С — имена обычно совпадают с XML_ID элемента. Если из фотостудии — нужна карта соответствия (CSV: артикул → имена файлов).
Загрузка через CFile и CIBlockElement
Базовый подход: читаем CSV с маппингом, для каждой строки загружаем файл через CFile::SaveFile() и обновляем элемент.
$csvRows = parseCsv('/import/mapping.csv'); // [['xml_id' => 'sku_001', 'files' => ['main.jpg', '2.jpg']]]
foreach ($csvRows as $row) {
// Находим элемент по XML_ID
$element = \Bitrix\Iblock\ElementTable::getList([
'filter' => ['XML_ID' => $row['xml_id'], 'IBLOCK_ID' => CATALOG_IBLOCK_ID],
'select' => ['ID'],
])->fetch();
if (!$element) continue;
$imageDir = '/import/images/' . $row['xml_id'] . '/';
$files = [];
foreach ($row['files'] as $i => $filename) {
$filePath = $imageDir . $filename;
if (!file_exists($filePath)) continue;
$fileId = \CFile::SaveFile([
'name' => $filename,
'type' => mime_content_type($filePath),
'tmp_name' => $filePath,
'error' => 0,
'size' => filesize($filePath),
], 'iblock');
if ($i === 0) {
// Первый файл — основное изображение
\CIBlockElement::Update($element['ID'], [
'PREVIEW_PICTURE' => \CFile::MakeFileArray($filePath),
'DETAIL_PICTURE' => \CFile::MakeFileArray($filePath),
]);
} else {
$files[] = ['VALUE' => \CFile::MakeFileArray($filePath)];
}
}
// Множественное свойство галереи
if (!empty($files)) {
\CIBlockElement::SetPropertyValues($element['ID'], CATALOG_IBLOCK_ID, $files, 'MORE_PHOTO');
}
}
CFile::MakeFileArray() не копирует файл — это просто массив-дескриптор. CFile::SaveFile() — фактическое сохранение и запись в b_file.
Производительность на больших объёмах
На каталоге 20 000+ позиций прямой цикл будет работать 2–4 часа и может упасть по таймауту или лимиту памяти. Несколько правил:
Разбивайте на пакеты. Обрабатывайте по 200–500 элементов за итерацию, сохраняйте прогресс в файл или таблицу.
Отключайте лишние обработчики событий. При массовом обновлении события OnBeforeIBlockElementUpdate и OnAfterIBlockElementUpdate могут вызвать цепочку тяжёлых операций (пересчёт цен, инвалидация кэша, обновление поиска). Временно отключите агенты и события, если они не нужны в момент импорта:
define('BX_DONT_PROCESS_EVENTS', true); // только если точно знаете последствия
// ИЛИ точечно:
\Bitrix\Main\EventManager::getInstance()->removeEventHandler('iblock', 'OnAfterIBlockElementUpdate', $handlerId);
Используйте CLI-скрипты. Запускайте через php -f import_images.php — нет ограничений по времени выполнения веб-запроса. Включите set_time_limit(0) и ini_set('memory_limit', '512M').
Очищайте кэш после завершения. После массовой загрузки сбросьте кэш инфоблоков: \Bitrix\Iblock\InformationBlock::cleanTagCache($iblockId). Не делайте это внутри цикла — только один раз в конце.
Обработка ошибок и логирование
$log = fopen('/var/log/image_import.log', 'a');
foreach ($csvRows as $row) {
try {
// ... обработка
fwrite($log, date('Y-m-d H:i:s') . " OK: {$row['xml_id']}\n");
} catch (\Throwable $e) {
fwrite($log, date('Y-m-d H:i:s') . " ERR: {$row['xml_id']} — {$e->getMessage()}\n");
}
}
Частые ошибки: файл не найден, неверный MIME-тип, дубликат в b_file (Битрикс проверяет по хэшу — повторная загрузка одного файла вернёт существующий ID).
Генерация миниатюр
После загрузки Битрикс создаёт миниатюры лениво — при первом обращении через компонент. Если нужно прогреть кэш сразу:
\CFile::ResizeImageGet($fileId, ['width' => 400, 'height' => 400], BX_RESIZE_IMAGE_PROPORTIONAL, true);
Или через CLI-утилиту, если на сервере настроен модуль ImageMagick.
Сроки выполнения
| Объём каталога | Ориентировочное время |
|---|---|
| До 1 000 товаров | 1–2 часа (настройка + загрузка) |
| 1 000–10 000 товаров | 4–8 часов |
| 10 000–50 000 товаров | 1–2 дня (включая тестирование и прогрев кэша) |







