Как исправить ошибку метода Записать при формировании XLSX в HTTP-сервисе 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке интеграционных решений на базе HTTP-сервисов в 1С:Предприятие программисты часто сталкиваются с ситуацией, когда код, успешно работающий в обычной обработке, выдает ошибку Ошибка при вызове метода контекста (Записать) при выполнении на стороне веб-сервера. Проанализируем типичный сценарий: формирование печатной формы в формате Excel и возврат её в теле ответа.

Разбор исходного кода и поиск уязвимых мест

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


Функция HTTPFileInfogetfieinfo(Запрос) 
    ПараметрыИзЗапроса = Новый Структура;
    ПараметрыИзЗапроса.Вставить("Параметр1" , Запрос["ПараметрыURL"].Получить("paramertrone"));
    ПараметрыИзЗапроса.Вставить("Параметр2" , Запрос["ПараметрыURL"].Получить("paramertrtwo"));	
    
    ТабДок = Новый ТабличныйДокумент;  
    Макет = ПолучитьОбщийМакет("МакетHTTP");
    Область = Макет.ПолучитьОбласть("Шапка");
    ТабДок.Вывести(Область);
    
    Область = Макет.ПолучитьОбласть("Строка"); 
    Область.Параметры.ИмяЧеловека = ПараметрыИзЗапроса.Параметр1;
    ТабДок.Вывести(Область);
    
    имяФайла = ПолучитьИмяВременногоФайла("xlsx");	
    // Здесь происходит ошибка
    ТабДок.Записать(имяФайла, ТипФайлаТабличногоДокумента.XLSX);
    
    ДвоичныеДанные = Новый ДвоичныеДанные(имяФайла);
    УдалитьФайлы(имяФайла);
    
    Ответ = Новый HTTPСервисОтвет(200);  
    Ответ.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанные);
    Возврат Ответ;	 
КонецФункции

На первый взгляд код выглядит корректно. Метод ПолучитьИмяВременногоФайла("xlsx") генерирует путь в системной временной папке. Однако, когда этот код исполняется внутри HTTP-сервиса, он запускается не от имени текущего пользователя Windows, а от имени системной учетной записи, под которой работает веб-сервер (IIS или Apache).

Причина №1: Права доступа веб-сервера

Выясним причину, почему метод Записать завершается аварийно. В большинстве случаев это связано с тем, что у пользователя IUSR или NetworkService (для IIS) отсутствуют права на запись в папку, путь к которой возвращает 1С. Хотя ПолучитьИмяВременногоФайла и выдает строку пути, сама попытка физического создания файла объектом ТабличныйДокумент блокируется операционной системой.

Для решения проблемы выполним следующие действия:

  1. Проверим, под какой учетной записью запущен пул приложений веб-сервера.
  2. Создадим на сервере отдельную папку (например, C:\Temp_1C_Web).
  3. Дадим права "Полный доступ" этой папке для группы Все (или конкретно для пользователя веб-сервера).
  4. В коде будем использовать явный путь для записи файла вместо автоматического получения временного имени.

Причина №2: Особенности работы на платформе Linux

Если сервер 1С:Предприятие или веб-сервер развернуты на операционной системе Linux, ситуация усложняется. Для записи ТабличногоДокумента в формат XLSX платформе требуются графические подсистемы для корректного рендеринга шрифтов и расчета ширины колонок.

Проанализируем необходимые компоненты для Linux:

Причина №3: Диагностика через Журнал регистрации

Поскольку в браузере мы видим лишь общую ошибку (чаще всего 500 Internal Server Error), нам необходимо заглянуть "под капот" системы. 1С всегда фиксирует детальное описание ошибки в Журнале регистрации.

Откроем Журнал регистрации в конфигураторе или в режиме "1С:Предприятие" (раздел Администрирование — Обслуживание). Нам нужно найти событие с уровнем "Ошибка", где в тексте будет указан стек вызова. Именно там будет написано что-то вроде: Ошибка доступа к файлу 'C:\Windows\Temp\v8_XXXX.xlsx'. Это станет окончательным подтверждением проблемы с правами.

Рекомендация по улучшению кода

Чтобы сделать код более надежным и избежать проблем с правами доступа к системным папкам, мы можем использовать конструкцию Попытка...Исключение и логировать ошибки. Также рассмотрим вариант использования более безопасных путей.


имяФайла = "C:\WebFiles\temp_" + СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "") + ".xlsx";
Попытка
    ТабДок.Записать(имяФайла, ТипФайлаТабличногоДокумента.XLSX);
Исключение
    ЗаписьЖурналаРегистрации("HTTP.ЗаписьФайла", УровеньЖурналаРегистрации.Ошибка, , , 
        "Не удалось записать файл: " + ПодробноеОписаниеОшибки(ИнформацияОбОшибке()));
    Ответ = Новый HTTPСервисОтвет(500);
    Ответ.УстановитьТелоИзСтроки("Внутренняя ошибка сервера при генерации файла.");
    Возврат Ответ;
КонецПопытки;

Итоги

Подведем итог нашего анализа. Если ваш HTTP-сервис "падает" на методе Записать:

  1. Проверьте права: Веб-сервер должен иметь права на запись в целевой каталог.
  2. Используйте Журнал регистрации: Это единственный способ увидеть реальную причину ошибки 500.
  3. Учитывайте ОС: На Linux не забудьте про шрифты и графические библиотеки.
  4. Явно задавайте пути: Иногда системная папка Temp бывает переполнена или заблокирована политиками безопасности, поэтому своя папка с настроенными правами — более надежное решение.

Следуя этим рекомендациям, мы сможем обеспечить стабильную работу механизмов выгрузки документов через веб-сервисы 1С.

← На главную