Файлы PHP в Bitrix: все аспекты работы с файловой системой

Раздел: Веб-разработка -> CMS Bitrix

В CMS Bitrix работа с файлами является неотъемлемой частью разработки: загрузка изображений, документов, обработка медиафайлов через API. В статье рассматриваются ключевые подходы к управлению файлами с использованием встроенных классов, таких как CFile, и методы интеграции с инфоблоками. Приводятся готовые примеры кода с пояснениями, а также разбираются типичные ошибки.

Основной способ: использование класса CFile

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

Наиболее эффективное решение - применение метода CFile::SaveFile, который принимает данные из $_FILES, массив параметров и идентификатор модуля. Пример ниже демонстрирует загрузку одного изображения с проверкой типа и размера.


<?php
// Файл upload.php в корне сайта
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['userfile'])) {
    $file = $_FILES['userfile'];
    $allowedMime = ['image/jpeg', 'image/png', 'image/gif'];
    $maxSize = 5 * 1024 * 1024; // 5 МБ

    if ($file['error'] !== UPLOAD_ERR_OK) {
        $error = 'Ошибка загрузки: код ' . $file['error'];
    } elseif (!in_array($file['type'], $allowedMime)) {
        $error = 'Недопустимый формат файла';
    } elseif ($file['size'] > $maxSize) {
        $error = 'Файл слишком большой';
    } else {
        $arFile = [
            'name' => $file['name'],
            'size' => $file['size'],
            'tmp_name' => $file['tmp_name'],
            'type' => $file['type'],
            'MODULE_ID' => 'main',
        ];
        $fid = CFile::SaveFile($arFile, 'uploads');
        if ($fid > 0) {
            $result = 'Файл сохранён. ID: ' . $fid . ', путь: ' . CFile::GetPath($fid);
        } else {
            $error = 'Не удалось сохранить файл';
        }
    }
}
?>

файл bitrix php (файл bitrix php)

Файл сохранён. ID: 123, путь: /upload/uploads/2024/01/image.jpg

File php bitrix (работа с файлами в bitrix (php))

Проблемы:

  • Если $_FILES пуст - стоит проверить enctype формы (multipart/form-data).
  • Большие файлы могут превышать лимиты PHP (upload_max_filesize, post_max_size). Рекомендуется увеличить значения в php.ini или через .htaccess.
  • Ошибка доступа к временной папке - проверить права на /tmp и /upload.

Как прикрепить файл к элементу инфоблока?

Для сохранения файла как свойства типа «Файл» элемента инфоблока используется CIBlockElement::SetPropertyValuesEx. Пример:


$arFile = CFile::MakeFileArray($_FILES['doc']['tmp_name']);
$propValue = ['VALUE' => $arFile, 'DESCRIPTION' => 'Документ'];
CIBlockElement::SetPropertyValuesEx($elementId, $iblockId, ['MY_FILE' => $propValue]);

В результате файл копируется в папку upload/iblock и привязывается к свойству.

Ошибки: свойство может не существовать - проверить код свойства в инфоблоке. Значение должно быть массивом с ключом VALUE.

Как обработать загруженное изображение (ресайз, кроп)?

Класс CFile предоставляет метод ResizeImageGet для создания копий изображения без загрузки в память:


$resized = CFile::ResizeImageGet(
    $fileId,
    ['width' => 300, 'height' => 200],
    BX_RESIZE_IMAGE_PROPORTIONAL_ALT,
    true
);
echo 'Путь к уменьшенной копии: ' . $resized['src'];
Путь к уменьшенной копии: /upload/resize_cache/main/abc/300_200_1/image.jpg

Проблемы: если исходный файл не изображение или повреждён, возвращается false. Нужно предварительно проверять CFile::IsImage($fileId).

Как загрузить несколько файлов одновременно?

Используется массив $_FILES['files']['name'] (с квадратными скобками в имени поля). Пример циклической обработки:


foreach ($_FILES['files']['tmp_name'] as $key => $tmpName) {
    if ($_FILES['files']['error'][$key] !== UPLOAD_ERR_OK) continue;
    $arFile = [
        'name' => $_FILES['files']['name'][$key],
        'size' => $_FILES['files']['size'][$key],
        'tmp_name' => $tmpName,
        'type' => $_FILES['files']['type'][$key],
        'MODULE_ID' => 'main',
    ];
    $fid = CFile::SaveFile($arFile, 'multi');
    // Сохранить fid в БД или в сессию
}

Типичная ошибка: неверная структура массива из формы - нужно указывать name="files[]" в HTML.

Как удалить файл через API?

Удаление записи о файле и самого файла с диска:


CFile::Delete($fileId);

Метод автоматически удаляет все производные (resize_cache), если они существуют.

Если файл используется другими сущностями (например, прикреплён к нескольким элементам), удаление может привести к ошибкам. Рекомендуется проверять файл через CFile::GetList или использовать CFile::Delete только при уверенности.

Ниже приведены расширенные примеры с подробными комментариями.

Пример 1. Загрузка файла с одновременным созданием миниатюры

Пример

// Загрузка, сохранение, ресайз и удаление оригинала (опционально)
function uploadAndThumbnail($fileArray, $thumbWidth = 150, $thumbHeight = 150) {
    $fileId = CFile::SaveFile($fileArray, 'products');
    if (!$fileId) return false;

    $thumb = CFile::ResizeImageGet($fileId, ['width' => $thumbWidth, 'height' => $thumbHeight], BX_RESIZE_IMAGE_EXACT);
    // Возвращаем массив с ID оригинала и путём к превью
    return [
        'ORIGINAL_ID' => $fileId,
        'THUMB_SRC'   => $thumb['src'],
    ];
}

// Использование
$result = uploadAndThumbnail([
    'name' => 'photo.jpg',
    'size' => 1024000,
    'tmp_name' => $_FILES['photo']['tmp_name'],
    'type' => 'image/jpeg',
    'MODULE_ID' => 'iblock',
], 200, 200);
if ($result) {
    echo 'Оригинал ID: ' . $result['ORIGINAL_ID'] . ', миниатюра: ' . $result['THUMB_SRC'];
} else {
    echo 'Ошибка';
}
Оригинал ID: 456, миниатюра: /upload/resize_cache/iblock/abc/200_200_1/photo.jpg

Пример 2. Получение всех файлов, прикреплённых к элементу инфоблока

Пример

$elementId = 123;
$iblockId = 5;
$propertyCode = 'FILES'; // множественное свойство типа «Файл»
$files = CIBlockElement::GetProperty($iblockId, $elementId, [], ['CODE' => $propertyCode]);
while ($file = $files->Fetch()) {
    if ($file['VALUE'] > 0) {
        $arFile = CFile::GetByID($file['VALUE'])->Fetch();
        echo 'Файл: ' . $arFile['ORIGINAL_NAME'] . ' (' . $arFile['FILE_SIZE'] . ' байт)
'; echo 'Путь: ' . CFile::GetPath($file['VALUE']) . '
'; } }
Файл: report.pdf (204800 байт)
Путь: /upload/iblock/abc/report.pdf
Файл: image.png (512000 байт)
Путь: /upload/iblock/def/image.png

Пример 3. Загрузка файла через асинхронный запрос (AJAX)

Пример

// front-end (JavaScript)
const formData = new FormData();
formData.append('file', fileInput.files[0]);
fetch('/ajax/upload.php', {
    method: 'POST',
    body: formData
}).then(res => res.json()).then(data => console.log(data));

// back-end (ajax/upload.php)
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_FILES['file'])) {
    $fid = CFile::SaveFile($_FILES['file'], 'ajax');
    if ($fid) {
        echo json_encode(['status' => 'ok', 'fileId' => $fid]);
    } else {
        echo json_encode(['status' => 'error']);
    }
}

Пример 4. Работа с временными файлами (CFile::MakeFileArray)

Пример

// Создать файл из строки и временно сохранить
$tempFile = CFile::MakeFileArray([
    'content' => 'Hello, world!',
    'filename' => 'hello.txt'
]);
$fid = CFile::SaveFile($tempFile, 'temp');
// $tempFile содержит путь и tmp_name, но после сохранения можно удалить
unlink($tempFile['tmp_name']);
Файл сохранён как временный, ID: 789

Пример 5. Обработка ошибок при загрузке через агент

Пример

// Агент для пакетной загрузки файлов из внешнего источника
function agentBatchUpload() {
    $urls = ['https://example.com/1.jpg', 'https://example.com/2.jpg'];
    foreach ($urls as $url) {
        $temp = CFile::MakeFileArray($url);
        if ($temp === false) {
            AddMessage2Log('Не удалось загрузить: ' . $url, 'upload_agent');
            continue;
        }
        CFile::SaveFile($temp, 'external');
    }
    return 'agentBatchUpload();';
}

Важно: в агенте не использовать глобальные переменные, все данные получать внутри функции.

Пример 6. Изменение прав доступа к файлу через API

Пример

$fileId = 100;
$arFile = CFile::GetByID($fileId)->Fetch();
$filePath = $_SERVER['DOCUMENT_ROOT'] . $arFile['SUBDIR'] . '/' . $arFile['FILE_NAME'];
chmod($filePath, 0644); // или 0444 для только чтения

Не рекомендуется изменять права на файлы, созданные системой, если нет веских причин.

Файл Bitrix PHP - comments

En
файл bitrix php (php)