Битрикс API загрузка во множественное UF поле тип файл в highloadblock

Короткая памятка по реальному кейсу: как правильно сохранить файлы в Highloadblock, чтобы они отображались в админке, а не просто лежали в b_file.

1. Подготовка поля в HL

В HL-блоке создайте пользовательское поле:

  • Код: UF_PHOTO (пример)
  • Тип: Файл
  • Множественное: Да (если нужно несколько файлов)

Если поле не множественное, передача массива файлов вызовет ошибку вида:

Поле "Фото" не может быть множественным.

2. Главная идея

Для UF-поля типа file в HL важно передавать правильный формат.

Рабочий формат для множественного поля:

  • сначала сохранить файл через CFile::SaveFile(...) и получить $fileId
  • затем для UF_PHOTO передать массив CFile::MakeFileArray($fileId)

3. Пример: множественная загрузка файлов в Highloadblock

use Bitrix\Highloadblock\HighloadBlockTable;

$hlBlock = HighloadBlockTable::getById($hlBlockId)->fetch();
$entity = HighloadBlockTable::compileEntity($hlBlock);
$dataClass = $entity->getDataClass();

$filesForUf = array();

foreach ($uploadedFiles as $file) {
    // $file в формате из $_FILES: name, type, tmp_name, error, size
    $fileId = (int)CFile::SaveFile($file, 'questionnaire');
    if ($fileId <= 0) {
        throw new \RuntimeException('Не удалось сохранить файл');
    }

    $fileArray = CFile::MakeFileArray($fileId);
    if (!is_array($fileArray)) {
        throw new \RuntimeException('Не удалось подготовить файл для UF-поля');
    }

    $filesForUf[] = $fileArray;
}

$result = $dataClass::add(array(
    'UF_USER_NAME' => (string)$userName,
    'UF_PHOTO' => $filesForUf,
));

if (!$result->isSuccess()) {
    throw new \RuntimeException(implode('; ', $result->getErrorMessages()));
}

4. Пример: одиночный файл в Highloadblock

$fileId = (int)CFile::SaveFile($file, 'questionnaire');
if ($fileId <= 0) {
    throw new \RuntimeException('Не удалось сохранить файл');
}

$fileForUf = CFile::MakeFileArray($fileId);

$result = $dataClass::add(array(
    'UF_DOCUMENT' => $fileForUf,
));

5. Валидация: разрешать только изображения

Можно настроить в админке, можно минимально безопасно проверять на сервере:

private function isImageFile(array $file)
{
    if (empty($file['tmp_name'])) {
        return false;
    }

    $imageCheckError = CFile::CheckImageFile($file);
    if (is_string($imageCheckError) && $imageCheckError !== '') {
        return false;
    }

    return @getimagesize($file['tmp_name']) !== false;
}

И в шаблоне формы:

<input type="file" name="attachments[]" multiple accept="image/*">

6. Что проверить, если файлы не видно в админке

  1. Поле точно типа Файл?
  2. Множественность поля совпадает с тем, что отправляете?
  3. В add()/update() передается именно формат CFile::MakeFileArray(...)?
  4. Файл реально попадает в b_file (есть fileId > 0)?

Если коротко: для HL-поля типа file чаще всего надежный путь — SaveFile -> MakeFileArray -> UF_FIELD.