При разработке интеграционных решений на базе HTTP-сервисов в 1С:Предприятие программисты часто сталкиваются с ситуацией, когда код, успешно работающий в обычной обработке, выдает ошибку Ошибка при вызове метода контекста (Записать) при выполнении на стороне веб-сервера. Проанализируем типичный сценарий: формирование печатной формы в формате Excel и возврат её в теле ответа.
Рассмотрим пример кода, который вызывает затруднения. В нем выполняется стандартная последовательность действий: получение параметров из запроса, заполнение области макета, вывод в табличный документ и попытка записи во временный файл.
Функция HTTPFileInfogetfieinfo(Запрос)
ПараметрыИзЗапроса = Новый Структура;
ПараметрыИзЗапроса.Вставить("Параметр1" , Запрос["ПараметрыURL"].Получить("paramertrone"));
ПараметрыИзЗапроса.Вставить("Параметр2" , Запрос["ПараметрыURL"].Получить("paramertrtwo"));
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьОбщийМакет("МакетHTTP");
Область = Макет.ПолучитьОбласть("Шапка");
ТабДок.Вывести(Область);
Область = Макет.ПолучитьОбласть("Строка");
Область.Параметры.ИмяЧеловека = ПараметрыИзЗапроса.Параметр1;
ТабДок.Вывести(Область);
имяФайла = ПолучитьИмяВременногоФайла("xlsx");
// Здесь происходит ошибка
ТабДок.Записать(имяФайла, ТипФайлаТабличногоДокумента.XLSX);
ДвоичныеДанные = Новый ДвоичныеДанные(имяФайла);
УдалитьФайлы(имяФайла);
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанные);
Возврат Ответ;
КонецФункции
На первый взгляд код выглядит корректно. Метод ПолучитьИмяВременногоФайла("xlsx") генерирует путь в системной временной папке. Однако, когда этот код исполняется внутри HTTP-сервиса, он запускается не от имени текущего пользователя Windows, а от имени системной учетной записи, под которой работает веб-сервер (IIS или Apache).
Выясним причину, почему метод Записать завершается аварийно. В большинстве случаев это связано с тем, что у пользователя IUSR или NetworkService (для IIS) отсутствуют права на запись в папку, путь к которой возвращает 1С. Хотя ПолучитьИмяВременногоФайла и выдает строку пути, сама попытка физического создания файла объектом ТабличныйДокумент блокируется операционной системой.
Для решения проблемы выполним следующие действия:
C:\Temp_1C_Web).Все (или конкретно для пользователя веб-сервера).Если сервер 1С:Предприятие или веб-сервер развернуты на операционной системе Linux, ситуация усложняется. Для записи ТабличногоДокумента в формат XLSX платформе требуются графические подсистемы для корректного рендеринга шрифтов и расчета ширины колонок.
Проанализируем необходимые компоненты для Linux:
libfontconfig1 и libfreetype6.ttf-mscorefonts-installer). Без них 1С не сможет вычислить размеры ячеек при конвертации в Excel.xvfb (виртуального X-сервера) для работы графических методов на сервере без монитора.Поскольку в браузере мы видим лишь общую ошибку (чаще всего 500 Internal Server Error), нам необходимо заглянуть "под капот" системы. 1С всегда фиксирует детальное описание ошибки в Журнале регистрации.
Откроем Журнал регистрации в конфигураторе или в режиме "1С:Предприятие" (раздел Администрирование — Обслуживание). Нам нужно найти событие с уровнем "Ошибка", где в тексте будет указан стек вызова. Именно там будет написано что-то вроде: Ошибка доступа к файлу 'C:\Windows\Temp\v8_XXXX.xlsx'. Это станет окончательным подтверждением проблемы с правами.
Чтобы сделать код более надежным и избежать проблем с правами доступа к системным папкам, мы можем использовать конструкцию Попытка...Исключение и логировать ошибки. Также рассмотрим вариант использования более безопасных путей.
имяФайла = "C:\WebFiles\temp_" + СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "") + ".xlsx";
Попытка
ТабДок.Записать(имяФайла, ТипФайлаТабличногоДокумента.XLSX);
Исключение
ЗаписьЖурналаРегистрации("HTTP.ЗаписьФайла", УровеньЖурналаРегистрации.Ошибка, , ,
"Не удалось записать файл: " + ПодробноеОписаниеОшибки(ИнформацияОбОшибке()));
Ответ = Новый HTTPСервисОтвет(500);
Ответ.УстановитьТелоИзСтроки("Внутренняя ошибка сервера при генерации файла.");
Возврат Ответ;
КонецПопытки;
Подведем итог нашего анализа. Если ваш HTTP-сервис "падает" на методе Записать:
500.Temp бывает переполнена или заблокирована политиками безопасности, поэтому своя папка с настроенными правами — более надежное решение.Следуя этим рекомендациям, мы сможем обеспечить стабильную работу механизмов выгрузки документов через веб-сервисы 1С.