Как загрузить и сохранить файл в 1С-Битрикс: CFile::MakeFileArray, SaveFile и D7 FileTable

Как загрузить и сохранить файл в 1С-Битрикс: CFile::MakeFileArray, SaveFile и D7 FileTable

Форма отправлена, в коде стоит CFile::SaveFile, а на выходе ноль и ни одной строки в таблице b_file? Чаще всего виноваты не "битрикс", а пустой $_FILES после лимита post_max_size=8M или отсутствие MODULE_ID в массиве файла. Ниже – как на CMS "1С-Битрикс: Управление сайтом" принять файл из формы, пройти цепочку MakeFileArray → SaveFile, привязать ID к инфоблоку или UF и отладить типичные сбои.

Класс CFile – стандартный способ зарегистрировать файл в ядре CMS: массив как у $_FILES, затем SaveFile с MODULE_ID и подпапкой в /upload. Успех – только целочисленный ID больше нуля и открывающийся SRC. При замене картинки передавайте old_file и del, иначе в b_file останется мусор. Это не Bitrix24: портальный Disk и REST Base64 здесь не используются.

В поиске часто попадают гайды про диск Bitrix24 – это другой продукт. Здесь только CMS: PHP, b_file и /upload. Update картинки – в гайде по Update, свойство "Файл" – в материале про свойства товаров, UF file – в статье про UF.

Разберите, когда нужен CFile на CMS, а не ручная заливка в /upload

Таблица сравнения: CFile, медиабиблиотека, FTP и Диск CRM — когда что использовать

CFile регистрирует файл в b_file и на диске /upload. Без него файл не привяжется к инфоблоку, UF или модулю. FTP подходит для статики, не для форм.

Способ Где файл живёт Когда выбирать Типичная ошибка
CFile::SaveFile b_file + /upload/subdir Форма, свойство, UF, свой модуль SaveFile вернул 0 без MODULE_ID
Медиабиблиотека (админка) Тот же b_file Редактор контента без кода Нет привязки к вашему API
FTP в /upload Только диск Статика, миграция архива Нет ID в b_file
Диск CRM-портала / REST Облако портала CRM, не CMS Копируют Base64 из helpdesk

Делайте: для кода в своём модуле всегда идите через CFile. Не делайте: не смешивайте примеры disk.folder.uploadfile из CRM-портала с CMS – у них другая схема хранения.

Проверьте upload_dir, права на /upload и лимиты PHP до отладки CFile

Чеклист: upload_dir, права /upload, лимиты PHP и MODULE_ID перед SaveFile

Перед SaveFile проверьте окружение – иначе отладка CFile займёт час, хотя виноват php.ini. На тестовом стенде типичная картина: файл 12 МБ, post_max_size=8M, $_FILES пустой, а разработчик копает SaveFile.

  1. Узнайте upload_dir: COption::GetOptionString('main', 'upload_dir', 'upload') – обычно это каталог /upload в корне сайта.
  2. Проверьте права на /upload и подпапку (например iblock/abc): веб-сервер должен писать файлы (часто 755 на папку, 644 на файлы).
  3. Сверьте php.ini: post_max_size должен быть не меньше upload_max_filesize. Иначе при большом файле PHP "молча" обнулит и $_POST, и $_FILES.
  4. Убедитесь, что форма с файлом имеет enctype="multipart/form-data" – без этого $_FILES пустой.
  5. Задайте MODULE_ID – код модуля-владельца (iblock, main, vendor.module) – иначе SaveFile часто возвращает false.
  6. Запустите bitrix_server_test.php из дистрибутива – тест загрузки покажет права и лимиты до вашего кода.

Делайте: при пустом $_FILES сначала смотрите CONTENT_LENGTH и post_max_size, а не CFile. Не делайте: не вызывайте SaveFile с сырым путём на диск без MakeFileArray – ядро ждёт структуру как у $_FILES (name, size, tmp_name, type).

Соберите массив файла через CFile::MakeFileArray

Схема workflow: $_FILES, MakeFileArray, SaveFile и ID в b_file

MakeFileArray строит массив для SaveFile. path – ID файла, путь на сервере или URL.

$arFile = $_FILES['DOCUMENT'];
$arFile = CFile::MakeFileArray('/var/www/site/import/price.pdf');
$arFile = CFile::MakeFileArray(12345);
$arFile = CFile::MakeFileArray('https://example.com/image.jpg');

Для пути на диске (не ID) с версии 12.5.7 передайте skipInternal = true. Без tmp_name добавьте content и name вручную. Делайте: вызовите CheckFile или CheckImageFile до SaveFile. Не делайте: не передавайте только имя без tmp_name – получите false на форуме разработчиков.

Сохраните файл через CFile::SaveFile и удалите старый при замене

SaveFile кладёт файл в подпапку upload и пишет строку в b_file. Успех – только ID больше нуля.

$arFile = $_FILES['PREVIEW_PICTURE'];
$arFile['MODULE_ID'] = 'iblock';

// Замена: старый ID 999, удалить после успеха
$arFile['old_file'] = 999;
$arFile['del'] = 'Y';

$fileId = CFile::SaveFile($arFile, 'iblock/custom');

if (intval($fileId) > 0) {
    // Привязка к элементу – см. гайд по Update
    CIBlockElement::Update($elementId, [
        'PREVIEW_PICTURE' => CFile::MakeFileArray($fileId),
    ]);
} else {
    // Диагностика: права, CheckFile, MODULE_ID, tmp_name
}

Свойство "Файл" – через PROPERTY_VALUES в гайде по Update. UF file – через $USER_FIELD_MANAGER в статье про UF. Удаление: CFile::Delete($oldId) или old_file + del в SaveFile.

Делайте: проверяйте intval($fileId) > 0 сразу после SaveFile. Не делайте: не оставляйте старый file ID в свойстве при ручной заливке нового файла без del – диск зарастёт дублями.

Отладите типичные сбои: SaveFile=0, пустой $_FILES, MIME

Таблица быстрой диагностики – что проверить, если цепочка оборвалась.

Симптом Вероятная причина Что сделать
$_FILES пустой post_max_size меньше размера тела запроса Увеличить post_max_size и upload_max_filesize, проверить enctype
SaveFile = 0 / false Нет MODULE_ID или битый массив Добавить MODULE_ID, полный name/tmp_name/type/size
Файл не на диске Нет прав на SUBDIR в /upload Права 755 на папку, bitrix_server_test.php
CheckFile отклонил Расширение или размер вне лимита Ослабить лимит или сменить расширение в настройках
ID есть, SRC 404 Файл удалили вручную с FTP Перезалить или очистить битую запись в b_file

Делайте: логируйте CheckFile и размер $_FILES до SaveFile. Не делайте: не считайте успехом файл в /upload без ID в b_file.

Прочитайте метаданные через GetFileArray и D7 FileTable

После сохранения путь – CFile::GetPath($id) или SRC из GetFileArray. Для пакетной выборки по списку ID удобнее D7, чем GetFileArray в цикле:

use Bitrix\Main\FileTable;

$rows = FileTable::getList([
    'filter' => ['@ID' => [101, 102, 103]],
    'select' => ['ID', 'ORIGINAL_NAME', 'SUBDIR', 'FILE_NAME'],
])->fetchAll();

// Ресайз картинки – по-прежнему CFile
$thumb = CFile::ResizeImageGet($fileId, ['width' => 200, 'height' => 200]);

FileTable читает b_file; новые файлы регистрируйте через SaveFile, не FileTable::add. Ресайз картинок – CFile::ResizeImageGet. В цикле по сотням элементов соберите ID и один getList вместо GetFileArray на каждой итерации – так вы избежите лишней нагрузки на диск.

Получите рабочий результат: чек-лист после загрузки

Перед выкладкой на прод пройдите список – так вы фиксируете, что цепочка $_FILES → MakeFileArray → SaveFile → привязка сработала.

  1. SaveFile вернул ID больше нуля.
  2. Строка в b_file с MODULE_ID и SUBDIR на месте.
  3. GetPath($id) открывается в браузере без 404.
  4. Старый file ID удалён при замене (del + old_file).
  5. Свойство инфоблока или UF показывает файл в форме редактирования.

Все пункты выполнены – загрузка работает. Обработчик можно вынести в свой модуль с тем же MODULE_ID.

Нужна помощь с формой загрузки в каталоге или кастомным свойством "Файл" – обсудим задачу и разберём стенд. Похожие кейсы по инфоблокам – в портфолио.

Автор: Максим Мольков, разработчик 1С-Битрикс.
Источники: справочник CFile, CFile::SaveFile, урок "Загрузка файлов", документация PHP по загрузке файлов.

Частые вопросы

Чем CFile отличается от прямой записи файла в /upload?

CFile регистрирует файл в таблице b_file и связывает его с модулями, свойствами и UF. Прямая запись на диск даёт файл без ID – компоненты и API инфоблока его не увидят. Для любой формы на CMS используйте MakeFileArray и SaveFile.

Как сохранить файл из $_FILES в свойство инфоблока?

Добавьте MODULE_ID в массив, вызовите SaveFile с подпапкой iblock, получите ID и передайте его в CIBlockElement::Update в PROPERTY_VALUES или в PREVIEW_PICTURE/DETAIL_PICTURE. Пошагово – в гайде по Update элемента инфоблока.

Почему CFile::SaveFile возвращает 0?

Проверьте MODULE_ID, полноту массива (name, tmp_name, type, size), результат CheckFile, права на /upload и лимиты post_max_size/upload_max_filesize. Пустой $_FILES при большом файле почти всегда означает превышение post_max_size, а не ошибку ядра.

Как удалить старый файл при обновлении картинки?

Перед SaveFile укажите old_file со старым ID и del = Y – ядро удалит предыдущую запись после успешной записи новой. Альтернатива – CFile::Delete($oldId) до Update, если новый файл уже сохранён отдельно.

Где на диске лежат загруженные через CFile файлы?

В каталоге upload_dir (по умолчанию /upload) в подпапке, которую вы передали вторым аргументом SaveFile, плюс SUBDIR из b_file. Точный веб-путь – CFile::GetPath($id) или поле SRC в GetFileArray.

Нужен ли FileTable::add вместо SaveFile?

Для новой загрузки с диска или из формы – нет, используйте CFile::SaveFile. FileTable удобен для чтения и массовой выборки по ID из b_file; физическое сохранение в /upload делает именно CFile.

Читайте также

Интеграции с 1С и API
1074 6 мин.

Как настроить регистрацию и личный кабинет покупателя на 1С-Битрикс?

Пошаговая настройка регистрации на сайте битрикс: Главный модуль, main.register, system.auth.form и sale.personal.section с историей заказов и 152-ФЗ.
Интеграции с 1С и API
941 6 мин.

Как настроить скидки и промокоды на 1С-Битрикс: правила корзины и купоны

Пошаговый гайд по скидкам в CMS-магазине: скидка на товар, правило корзины от суммы, купоны с лимитом, приоритеты без конфликтов и тестовый заказ. Не Bitrix24.
Интеграции с 1С и API
759 15 мин.

Что такое компонент в Битриксе и как он работает

Каждый разработчик, впервые столкнувшийся с Битриксом, проходит через своеобразный обряд посвящения. Вначале кажется, что это просто CMS, где можно поправить HTML в визуальном редакторе или дописать пару строк CSS. Но однажды наступает момент, когда нужно изменить логику вывода новостей, отфильтровать товары по хитрому свойству или добавить на страницу нечто совершенно новое. И тут он впервые слышит это слово — «компонент». Для многих этот момент становится стеной. Система, казавшаяся понятной, вдруг превращается в черный ящик, полный непонятных файлов и странных переменных. Но стоит лишь раз заглянуть под капот, как эта стена рассыпается, превращаясь в набор удивительно логичных и мощных строительных блоков. Понимание компонентов — это тот самый щелчок, после которого разработка на Битрикс из мучения превращается в творчество.

Эта статья — ваш проводник в мир компонентов «1С-Битрикс». Мы не будем сыпать сухими терминами из документации. Вместо этого мы совершим путешествие: от философии, заложенной в эту архитектуру, до мельчайших деталей её работы. Мы разберем компонент на атомы — его файлы, логику, шаблон, параметры — и соберем обратно, чтобы вы не просто знали, что это, но и глубоко понимали, почему это работает именно так. Это знание — ключ к эффективной и профессиональной разработке на Битрикс.

Интеграции с 1С и API
718 2 мин.

Установка Composer в 1С-Битрикс

Установка Composer в проекте на 1С-Битрикс требует учета особенностей платформы, чтобы обеспечить корректную работу и интеграцию с системой.