CFile::SaveFile ожидает массив в определённом формате —
но не всегда исходные данные приходят готовым файлом с диска.
Разберём CFile::MakeFileArray, который упрощает
подготовку такого массива из пути или URL, избавляя от ручного
формирования структуры вручную.
Базовое использование с локальным путём
<?php
$fileArray = CFile::MakeFileArray('/path/to/local/image.jpg');
$fileId = CFile::SaveFile($fileArray, 'catalog');
MakeFileArray берёт на себя формирование массива
с нужными ключами (name, type,
tmp_name, size) на основе уже
существующего на диске файла — избавляет от ручного вызова
filesize, определения MIME-типа и сборки массива
вручную для каждого случая программного сохранения файла.
Использование с внешним URL
<?php
$fileArray = CFile::MakeFileArray('https://supplier.example.ru/images/product123.jpg');
if ($fileArray) {
$fileId = CFile::SaveFile($fileArray, 'catalog');
}
Метод умеет принимать не только локальный путь, но и внешний URL — под капотом это фактически скачивание файла по указанному адресу во временное расположение с последующим формированием массива на его основе. Это удобно при импорте товаров с изображениями по прямым ссылкам от поставщика, где сами файлы физически не находятся на локальном сервере.
Нужна помощь с Битрикс?
Обработка неудачной загрузки по URL
<?php
$fileArray = CFile::MakeFileArray($imageUrl);
if ($fileArray === false || empty($fileArray['tmp_name'])) {
AddMessage2Log('Не удалось загрузить изображение: ' . $imageUrl, 'import');
} else {
$fileId = CFile::SaveFile($fileArray, 'catalog');
}
Внешний URL может оказаться недоступен (сервер поставщика лежит,
ссылка устарела, изменился формат адреса) — метод в этом случае
не выбрасывает исключение, а возвращает результат, требующий
явной проверки перед передачей в SaveFile, иначе
ошибка загрузки конкретного изображения молча прервёт весь
процесс импорта на этой записи без понятного объяснения причины.
Производительность при массовой загрузке по URL
Как и при любой другой сетевой операции в цикле импорта, массовая загрузка изображений по внешним URL для сотен и тысяч товаров — заметно более медленная операция, чем работа с локальными файлами, — при планировании времени выполнения массового импорта с таким этапом стоит закладывать это замедление заранее, а не удивляться тому, что импорт с изображениями идёт заметно дольше, чем чистый импорт текстовых данных без картинок.
Ограничение по таймауту сетевого запроса
Метод не даёт прямого контроля над таймаутом сетевого запроса
за файлом по URL так же явно, как это делает
HttpClient с методом setTimeout — для
массового импорта с большим числом потенциально недоступных
ссылок это может привести к неожиданно долгому суммарному времени
выполнения из-за ожидания ответа от зависших источников. В таких
сценариях иногда практичнее скачивать файл вручную через
HttpClient с явным таймаутом, а уже локальный
результат передавать в MakeFileArray.
Комбинация с CIBlockElement::Add
<?php
$fileArray = CFile::MakeFileArray($imageUrl);
$el = new CIBlockElement;
$el->Add([
'IBLOCK_ID' => $iblockId,
'NAME' => $productName,
'PREVIEW_PICTURE' => $fileArray, // напрямую массив, без предварительного SaveFile
]);
Полезная деталь: массив, сформированный MakeFileArray,
можно передавать напрямую в поле изображения при добавлении
элемента инфоблока, минуя отдельный вызов SaveFile, —
CIBlockElement::Add сам вызывает сохранение файла
внутри себя, получив массив в ожидаемом формате.
Частые ошибки
- Результат MakeFileArray не проверяется перед SaveFile. Неудачная загрузка по недоступному URL остаётся незамеченной.
- Нет учёта замедления импорта из-за сетевых загрузок. Массовый импорт с изображениями по URL занимает заметно больше времени, чем ожидалось.
- Ручное формирование массива вместо MakeFileArray там, где он подходит. Избыточный код для задачи, уже закрытой готовым методом.
Итог
CFile::MakeFileArray упрощает подготовку файла
для сохранения как из локального пути, так и из внешнего URL,
избавляя от ручной сборки массива с нужными ключами. При работе
с внешними ссылками обязательна проверка результата на неудачную
загрузку, а для больших объёмов импорта с изображениями стоит
заранее закладывать заметное замедление относительно импорта
без сетевых загрузок файлов.
