Как вывести ссылку на файл из свойства инфоблока в 1С-Битрикс

  • 3265
   
Разделы

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


По возможности указываю ссылки на источники.


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

Частный вебмастер по разработке сайтов на 1С Битрикс и WordPress

В свойствах инфоблока 1С-Битрикс типа «Файл» хранится не готовая ссылка, а ID зарегистрированного файла. Поэтому значение свойства нельзя просто подставить в href или src.

Получить путь к файлу можно стандартным методом CFile::GetPath(). Если кроме ссылки нужны имя файла, размер, MIME-тип или другие данные, удобнее использовать CFile::GetFileArray().

Коротко: если нужен только путь к файлу — используйте CFile::GetPath(). Если нужна дополнительная информация о файле — CFile::GetFileArray().

Как получить ссылку на файл через CFile::GetPath()

Допустим, у элемента инфоблока есть свойство с кодом ATT_FILE типа «Файл».

ID загруженного файла находится в:

<?php
$fileId = $arResult['PROPERTIES']['ATT_FILE']['VALUE'];
?>

Получаем путь к файлу:

<?php
$fileId = (int)($arResult['PROPERTIES']['ATT_FILE']['VALUE'] ?? 0);

$filePath = $fileId
    ? CFile::GetPath($fileId)
    : null;
?>

Метод вернёт путь от корня сайта, например /upload/iblock/123/document.pdf.

Если файл с таким ID не найден, результатом будет null.

Вывод ссылки на файл

Самый простой рабочий пример для шаблона компонента template.php:

<?php
$fileId = (int)($arResult['PROPERTIES']['ATT_FILE']['VALUE'] ?? 0);
$filePath = $fileId ? CFile::GetPath($fileId) : null;
?>

<?php if ($filePath): ?>

    <a
        href="<?= htmlspecialcharsbx($filePath) ?>"
        target="_blank"
        rel="noopener"
    >
        Открыть файл
    </a>

<?php endif; ?>

Ссылка на скачивание файла

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

<?php
$fileId = (int)($arResult['PROPERTIES']['ATT_FILE']['VALUE'] ?? 0);
$filePath = $fileId ? CFile::GetPath($fileId) : null;
?>

<?php if ($filePath): ?>

    <a
        href="<?= htmlspecialcharsbx($filePath) ?>"
        download
    >
        Скачать файл
    </a>

<?php endif; ?>

Для обычных файлов, находящихся на этом же сайте, такого варианта достаточно.

Как вывести имя и размер файла

У CFile::GetPath() есть один недостаток: метод возвращает только путь. Если нужно показать пользователю настоящее имя файла, размер или его тип, используйте CFile::GetFileArray().

<?php
$fileId = (int)($arResult['PROPERTIES']['ATT_FILE']['VALUE'] ?? 0);
$file = $fileId ? CFile::GetFileArray($fileId) : false;
?>

<?php if ($file): ?>

    <a
        href="<?= htmlspecialcharsbx($file['SRC']) ?>"
        download
    >
        <?= htmlspecialcharsbx(
            $file['ORIGINAL_NAME'] ?: $file['FILE_NAME']
        ) ?>
    </a>

    <span>
        <?= CFile::FormatSize((int)$file['FILE_SIZE']) ?>
    </span>

<?php endif; ?>

В массиве $file доступны, в частности:

Поле Что содержит
SRC Путь к файлу
ORIGINAL_NAME Исходное имя загруженного файла
FILE_NAME Имя файла на сервере
FILE_SIZE Размер файла в байтах
CONTENT_TYPE MIME-тип файла
WIDTH Ширина изображения, если это картинка
HEIGHT Высота изображения

Вывод нескольких файлов из множественного свойства

Если свойство ATT_FILES множественное, в VALUE будет массив ID файлов.

Например, выведем список файлов с названием и размером:

<?php
$fileIds = $arResult['PROPERTIES']['ATT_FILES']['VALUE'] ?? [];

foreach ($fileIds as $fileId) {

    $file = CFile::GetFileArray((int)$fileId);

    if (!$file) {
        continue;
    }

    $fileName = $file['ORIGINAL_NAME'] ?: $file['FILE_NAME'];
    ?>

    <div class="file-item">

        <a
            href="<?= htmlspecialcharsbx($file['SRC']) ?>"
            download
        >
            <?= htmlspecialcharsbx($fileName) ?>
        </a>

        <span class="file-item__size">
            <?= CFile::FormatSize((int)$file['FILE_SIZE']) ?>
        </span>

    </div>

    <?php
}
?>

Как вывести описание файла

У файлового свойства Битрикса можно включить описание. Для множественного свойства массив описаний находится в DESCRIPTION и соответствует массиву файлов по индексу.

<?php
$property = $arResult['PROPERTIES']['ATT_FILES'] ?? [];

$fileIds = $property['VALUE'] ?? [];
$descriptions = $property['DESCRIPTION'] ?? [];

foreach ($fileIds as $index => $fileId) {

    $file = CFile::GetFileArray((int)$fileId);

    if (!$file) {
        continue;
    }

    $fileName = $file['ORIGINAL_NAME'] ?: $file['FILE_NAME'];
    $description = $descriptions[$index] ?? '';
    ?>

    <div class="file-item">

        <a
            href="<?= htmlspecialcharsbx($file['SRC']) ?>"
            download
        >
            <?= htmlspecialcharsbx($fileName) ?>
        </a>

        <?php if ($description): ?>

            <div class="file-item__description">
                <?= htmlspecialcharsbx($description) ?>
            </div>

        <?php endif; ?>

    </div>

    <?php
}
?>

Вывод изображения из файлового свойства

Если в свойстве хранится изображение, полученный путь можно сразу использовать в src.

<?php
$imageId = (int)($arResult['PROPERTIES']['ATT_IMG']['VALUE'] ?? 0);
$imageSrc = $imageId ? CFile::GetPath($imageId) : null;
?>

<?php if ($imageSrc): ?>

    <img
        src="<?= htmlspecialcharsbx($imageSrc) ?>"
        alt="<?= htmlspecialcharsbx($arResult['NAME']) ?>"
        loading="lazy"
    >

<?php endif; ?>
Если на странице нужно выводить уменьшенное превью изображения, лучше не загружать оригинал и уменьшать его через CSS. Для этого используйте CFile::ResizeImageGet().

Галерея из множественного свойства

Для нескольких изображений принцип тот же: перебираем ID файлов и получаем путь каждого изображения через CFile::GetPath().

<?php
$imageIds = $arResult['PROPERTIES']['ATT_IMG']['VALUE'] ?? [];

foreach ($imageIds as $imageId) {

    $imageSrc = CFile::GetPath((int)$imageId);

    if (!$imageSrc) {
        continue;
    }
    ?>

    <div class="gallery__item">

        <img
            src="<?= htmlspecialcharsbx($imageSrc) ?>"
            alt="<?= htmlspecialcharsbx($arResult['NAME']) ?>"
            loading="lazy"
        >

    </div>

    <?php
}
?>

Открытие изображения через Fancybox

Если на проекте уже подключён Fancybox, оригинальное изображение можно открывать по клику:

<?php
$imageIds = $arResult['PROPERTIES']['ATT_IMG']['VALUE'] ?? [];

foreach ($imageIds as $imageId) {

    $imageSrc = CFile::GetPath((int)$imageId);

    if (!$imageSrc) {
        continue;
    }
    ?>

    <a
        href="<?= htmlspecialcharsbx($imageSrc) ?>"
        data-fancybox="gallery"
    >

        <img
            src="<?= htmlspecialcharsbx($imageSrc) ?>"
            alt="<?= htmlspecialcharsbx($arResult['NAME']) ?>"
            loading="lazy"
        >

    </a>

    <?php
}
?>

Универсальный пример для списка файлов

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

Ниже готовый вариант, который можно вставить в template.php:

<?php
$property = $arResult['PROPERTIES']['ATT_FILES'] ?? [];

$fileIds = $property['VALUE'] ?? [];
$descriptions = $property['DESCRIPTION'] ?? [];

if (!is_array($fileIds)) {
    $fileIds = $fileIds ? [$fileIds] : [];
}

if (!is_array($descriptions)) {
    $descriptions = [$descriptions];
}
?>

<?php if ($fileIds): ?>

    <div class="files">

        <?php foreach ($fileIds as $index => $fileId): ?>

            <?php
            $file = CFile::GetFileArray((int)$fileId);

            if (!$file) {
                continue;
            }

            $fileName = $file['ORIGINAL_NAME'] ?: $file['FILE_NAME'];
            $description = $descriptions[$index] ?? '';
            ?>

            <div class="files__item">

                <a
                    class="files__link"
                    href="<?= htmlspecialcharsbx($file['SRC']) ?>"
                    download
                >
                    <?= htmlspecialcharsbx($fileName) ?>
                </a>

                <span class="files__size">
                    <?= CFile::FormatSize((int)$file['FILE_SIZE']) ?>
                </span>

                <?php if ($description): ?>

                    <div class="files__description">
                        <?= htmlspecialcharsbx($description) ?>
                    </div>

                <?php endif; ?>

            </div>

        <?php endforeach; ?>

    </div>

<?php endif; ?>

CFile::GetPath() или CFile::GetFileArray()

Задача Что использовать
Получить только путь к файлу CFile::GetPath()
Получить имя файла CFile::GetFileArray()
Получить размер файла CFile::GetFileArray()
Получить MIME-тип CFile::GetFileArray()
Вывести изображение CFile::GetPath()
Вывести список документов с информацией CFile::GetFileArray()

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

Использование ID файла вместо ссылки

Такой вариант работать не будет:

<a href="<?= $arResult['PROPERTIES']['ATT_FILE']['VALUE'] ?>">
    Скачать
</a>

В VALUE находится ID файла, например 1257, а не путь к нему.

Отсутствие проверки файла

Не стоит сразу выводить результат метода без проверки. Свойство может оказаться пустым, либо файл мог быть удалён.

<?php
$filePath = CFile::GetPath($fileId);

if ($filePath) {
    // Файл существует
}
?>

Получение имени файла из URL

Если требуется исходное название загруженного документа, не нужно разбирать путь через basename().

Битрикс может изменить имя физического файла на сервере. Для отображения пользователю лучше использовать поле ORIGINAL_NAME из CFile::GetFileArray().

Итог

Для работы с файловыми свойствами инфоблока в большинстве случаев достаточно двух стандартных методов Битрикса:

  • CFile::GetPath() — получить путь к файлу по его ID;
  • CFile::GetFileArray() — получить путь, имя, размер, MIME-тип и другую информацию о файле.

Если нужен простой href или src, используйте CFile::GetPath(). Если выводите полноценный список документов с названием и размером — удобнее сразу использовать CFile::GetFileArray().

Комментарии

CAPTCHA
Комментарий отправлены на валидацию!