Yandex Metrika
sanches.free 19 просмотров

Длинные значения свойств инфоблока и тяжёлые выгрузки: LONGTEXT и сброс буфера

Свойства инфоблока и объём строки

Значения многих типов свойств попадают в таблицу b_iblock_element_property. Если ядро обрезает ваш HTML или JSON уже на этапе сохранения, причина часто двойная: ограничение типа столбца в базе и жёсткий порог длины в коде сохранения, который для MySQL рассчитан под старый лимит MEDIUMTEXT, а для других СУБД — заметно меньше.

Расширение столбца в MySQL

На связке «Битрикс + MySQL» разумный шаг перед спорными «костылями» в PHP — перевести VALUE в LONGTEXT, чтобы строка свойства могла занимать до порядка гигабайта на уровне типа данных (реальный предел всё равно надо сверять с настройками сервера и здравым смыслом по UX).

ALTER TABLE `b_iblock_element_property`
MODIFY `VALUE` LONGTEXT NOT NULL;

Согласовать код ядра

Параллельно имеет смысл посмотреть фрагмент, где задаётся максимальная длина для записи свойства в PHP: типичный шаблон сравнивает $DB->type с MYSQL и задаёт два разных потолка. После изменения типа столбца логично поднять и программный лимит, например до десяти мебибайт в символьном виде или до значения, которое допускает ваш сценарий импорта. Любую правку в ядре фиксируйте патчем или переопределением так, чтобы обновление не затёрло её молча; общий порядок работы описан отдельно в материале «Как патчить Битрикс» на том же ресурсе.

if ($DB->type === "MYSQL")
{
	$sliceCap = 10 * 1024 * 1024; // граница в байтах для длинной строки
}
else
{
	$sliceCap = 2048;
}

Большие файлы «из PHP» без обрыва

Если архив или отчёт собирается на лету и вес доходит до десятков мегабайт, браузер иногда получает неполное тело. Частый виновник — включённая буферизация вывода до того, как пошёл бинарный поток по readfile().

Последовательность, которая обычно спасает

Сначала сбросьте уже начатый ответ приложения через $APPLICATION->RestartBuffer(), затем выставьте заголовки вложения и длину содержимого. Перед потоковой отправкой аккуратно снимите вложенные уровни ob_* (обычно делают ограниченный цикл, чтобы не уйти в бесконечность при ошибочной конфигурации). После readfile() удалите временный файл и завершите скрипт без лишнего вывода.

global $APPLICATION;

$APPLICATION->RestartBuffer();

$mime = "application/zip";
$downloadLabel = sprintf('attachment; filename="%s"', basename($stagingArchivePath));

header('Content-Type: ' . $mime);
header('Content-Disposition: ' . $downloadLabel);
header('Content-Length: ' . filesize($stagingArchivePath));

$nested = ob_get_level();
if ($nested > 16)
{
	$nested = 16;
}

while ($nested-- > 0)
{
	ob_end_flush();
}

readfile($stagingArchivePath);
@unlink($stagingArchivePath);
die();

Чеклист

  • Перед правкой таблицы сделайте бэкап и проверку на staging.
  • После ALTER и правки порога в коде прогоните один «проброс» свойства большим текстом через админку или API.
  • Для выгрузок логируйте реальный размер файла и сравнивайте с объёмом, который приходит в браузер по Network.

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии