Главная » API Битрикс » CFile » CFile::SaveFile и Delete — работа с файлами в Битрикс

CFile::SaveFile и Delete — работа с файлами в Битрикс

Схема сохранения и удаления файла через CFile::SaveFile и CFile::Delete в Битрикс

CFile::SaveFile — низкоуровневый способ сохранить файл в системе управления файлами Битрикса вручную, минуя стандартную форму загрузки. Разберём, когда он нужен и какие подводные камни есть у прямого сохранения файла из кода.

Базовый вызов

<?php

$fileArray = [
    'name' => 'report.pdf',
    'type' => 'application/pdf',
    'tmp_name' => '/tmp/generated_report_123.pdf',
    'size' => filesize('/tmp/generated_report_123.pdf'),
];

$fileId = CFile::SaveFile($fileArray, 'reports');

if ($fileId) {
    echo 'Файл сохранён, ID: ' . $fileId;
}

Метод ожидает массив в формате, похожем на структуру $_FILES, — с полями name, type, tmp_name и size. Второй параметр — подпапка внутри каталога upload/, куда физически попадёт файл.

Сохранение сгенерированного контента без временного файла на диске

Частый сценарий — файл существует только в памяти (например, сформированный CSV-экспорт), и создавать его сначала на диске избыточно:

<?php

$csvContent = "Название;Цена\nТовар 1;1000\nТовар 2;2000\n";
$tmpPath = sys_get_temp_dir() . '/' . uniqid('export_') . '.csv';

file_put_contents($tmpPath, $csvContent);

$fileId = CFile::SaveFile([
    'name' => 'export.csv',
    'type' => 'text/csv',
    'tmp_name' => $tmpPath,
    'size' => filesize($tmpPath),
], 'exports');

unlink($tmpPath); // временный файл больше не нужен, CFile уже скопировал его

tmp_name обязателен — метод физически копирует файл оттуда в целевой каталог, поэтому файл должен реально существовать на диске в момент вызова, пусть даже временно.

Нужна помощь с Битрикс?





    Привязка файла к элементу инфоблока

    <?php
    
    $fileId = CFile::SaveFile($fileArray, 'catalog');
    
    $el = new CIBlockElement;
    $el->Update($elementId, [
        'PROPERTY_VALUES' => [
            'DOCUMENT' => $fileId,
        ],
    ]);

    Полученный $fileId — это ID записи в таблице файлов (b_file), который можно записать в файловое свойство инфоблока, поле пользователя или любое другое место, ожидающее ID файла Битрикса.

    Удаление файла

    <?php
    
    CFile::Delete($fileId);

    Важная деталь: Delete удаляет запись и физический файл только если на него не осталось других ссылок в системе. Если тот же $fileId используется где-то ещё (например, в нескольких элементах через общее свойство), метод уменьшает счётчик ссылок, а сам файл остаётся на диске до полного освобождения.

    Замена файла без потери старого ID

    <?php
    
    $newFileId = CFile::SaveFile($newFileArray, 'catalog');
    
    CFile::Delete($oldFileId); // старый файл корректно освобождается
    
    $el->Update($elementId, [
        'PROPERTY_VALUES' => ['DOCUMENT' => $newFileId],
    ]);

    Частая ошибка — забыть удалить старый файл при замене, из-за чего каталог upload/ постепенно накапливает файлы-сироты, на которые уже никто не ссылается из базы данных.

    Проверка типа и размера перед сохранением

    SaveFile не проверяет содержимое файла на соответствие заявленному MIME-типу и не ограничивает размер — эти проверки на стороне вызывающего кода обязательны, если файл формируется из данных, на которые нельзя полагаться (например, приходит через внешний API или загружается пользователем окольным путём, минуя штатную форму с её собственными проверками):

    <?php
    
    $allowedExtensions = ['pdf', 'csv', 'xlsx'];
    $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
    
    if (!in_array($ext, $allowedExtensions, true)) {
        throw new \InvalidArgumentException('Недопустимый тип файла');
    }
    
    if (filesize($tmpPath) > 10 * 1024 * 1024) {
        throw new \InvalidArgumentException('Файл превышает 10 МБ');
    }

    Частые ошибки

    • tmp_name указывает на несуществующий файл. Метод не сможет скопировать файл и вернёт ошибку сохранения.
    • Забыли удалить старый файл при замене. Каталог upload/ постепенно накапливает файлы-сироты.
    • Нет проверки типа и размера при программном сохранении. В систему попадают файлы, которые не прошли бы штатную форму загрузки.

    Итог

    CFile::SaveFile сохраняет файл из временного пути в файловую систему Битрикса и возвращает ID, пригодный для любого файлового поля системы. При замене файла важно освобождать старый через CFile::Delete, а при программном формировании файла — проверять тип и размер самостоятельно, поскольку штатные проверки формы загрузки здесь не участвуют.

    Нужна помощь с Битрикс?

    Исправим ошибку, доработаем сайт, ускорим Битрикс или поможем разобраться с проблемой.

    Услуги
    База знаний