Настройка скачивания сертификатов на товары 1С-Битрикс
Разница между отображением и скачиванием сертификатов — не только в кнопке «Скачать». Правильная настройка скачивания предполагает: контроль доступа к файлам, корректные имена файлов при скачивании, защиту от прямого перебора URL, и при необходимости — учёт скачиваний.
Прямые ссылки vs. контролируемая отдача файлов
Если файлы хранятся в /upload/ — прямые ссылки работают, но любой, кто знает URL, скачает файл без авторизации. Для публичных сертификатов это нормально. Для внутренних документов — нет.
Прямая ссылка (простейший вариант):
$fileInfo = \CFile::GetFileArray($fileId);
echo '<a href="' . $fileInfo['SRC'] . '" download>';
Контролируемая отдача через обработчик (если нужен контроль доступа или красивые имена файлов):
Создаёте файл /local/ajax/download-cert.php:
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';
$fileId = (int)$_GET['id'];
$productId = (int)$_GET['product_id'];
// Проверяем, что файл реально привязан к товару (защита от перебора)
$prop = \CIBlockElement::GetProperty(
CATALOG_IBLOCK_ID,
$productId,
[],
['CODE' => 'CERTIFICATE']
);
$allowed = false;
while ($p = $prop->Fetch()) {
if ((int)$p['VALUE'] === $fileId) {
$allowed = true;
break;
}
}
if (!$allowed) {
header('HTTP/1.0 403 Forbidden');
die();
}
$fileInfo = \CFile::GetFileArray($fileId);
if (!$fileInfo) {
header('HTTP/1.0 404 Not Found');
die();
}
$filePath = $_SERVER['DOCUMENT_ROOT'] . $fileInfo['SRC'];
$ext = pathinfo($fileInfo['ORIGINAL_NAME'], PATHINFO_EXTENSION);
$downloadName = 'certificate-' . $productId . '.' . $ext;
header('Content-Type: ' . $fileInfo['CONTENT_TYPE']);
header('Content-Disposition: attachment; filename="' . $downloadName . '"');
header('Content-Length: ' . filesize($filePath));
readfile($filePath);
exit();
Ссылка для скачивания:
<a href="/local/ajax/download-cert.php?id=<?= $fileId ?>&product_id=<?= $productId ?>">
Скачать сертификат
</a>
Учёт скачиваний
Если нужно знать, сколько раз скачивали сертификат, — логируете в отдельную таблицу или через события Битрикса. Простейший вариант — таблица b_user_counter не подходит по семантике, делаете свою через \Bitrix\Main\Application::getConnection()->query() или создаёте HL-инфоблок CertDownloads с полями: UF_PRODUCT_ID, UF_FILE_ID, UF_USER_ID, UF_DATE, UF_IP.
Пакетное скачивание нескольких сертификатов
Если у товара несколько сертификатов и хотите предложить скачать все одним ZIP — используете PHP ZipArchive:
$zip = new ZipArchive();
$tmpFile = tempnam(sys_get_temp_dir(), 'certs_');
$zip->open($tmpFile, ZipArchive::CREATE);
foreach ($fileIds as $fid) {
$fi = \CFile::GetFileArray($fid);
$zip->addFile($_SERVER['DOCUMENT_ROOT'] . $fi['SRC'], $fi['ORIGINAL_NAME']);
}
$zip->close();
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="certificates.zip"');
readfile($tmpFile);
unlink($tmpFile);
Защита папки upload
Если хотите полностью закрыть прямой доступ к файлам в папке — кладёте их в /upload/protected/ и добавляете в .htaccess этой папки:
Deny from all
Тогда всё скачивание идёт только через ваш обработчик, и прямые URL не работают.
| Этап | Время |
|---|---|
| Настройка прямых ссылок на скачивание | 1–2 ч |
| Разработка контролируемого обработчика | 3–5 ч |
| Учёт скачиваний (опционально) | 2–3 ч |
| Пакетное скачивание ZIP (опционально) | 2–4 ч |







