При интеграции 1С с внешними веб-сервисами, особенно построенными на базе технологий Oracle (шлюзы mod_plsql), разработчики часто сталкиваются с ситуацией, когда прямая ссылка, работающая в браузере, не позволяет сразу скачать файл программно. Вместо ожидаемого Excel-файла или PDF-документа система получает HTML-код страницы с параметрами отчета. Рассмотрим подробно, почему так происходит, как проанализировать проблему и какими методами в 1С можно добиться корректного сохранения файла на диск.
Начнем с классической ситуации: у нас есть ссылка вида http://server/pls/info/report.run?param1=val1&p_action=Start. При вводе этой ссылки в адресную строку браузера происходит магия — браузер на мгновение открывает страницу, а затем автоматически инициирует загрузку файла. Однако при использовании объекта 1С HTTPСоединение метод Получить() возвращает лишь текстовое содержимое (HTML-код формы).
Выясним причину такого поведения. Разберем ситуацию: браузер — это сложный инструмент, который умеет исполнять JavaScript, обрабатывать редиректы и интерпретировать мета-теги. Веб-сервер часто настроен так, что первый запрос (GET) лишь инициализирует сессию или отображает форму, а само формирование файла происходит после нажатия кнопки или выполнения скрипта. В 1С мы работаем на уровне «чистых» протоколов, поэтому нам нужно повторить в точности те действия, которые браузер совершает «под капотом».
Прежде чем писать код в 1С, проанализируем ситуацию с помощью инструментов разработчика в браузере (клавиша F12, вкладка Network/Сеть). Это самый важный этап, который позволит нам увидеть реальную картину взаимодействия:
Если мы видим, что после GET-запроса следует POST-запрос на тот же или другой адрес, это означает, что сервер ожидает именно отправку данных формы. В заголовках ответа сервера на успешный запрос файла мы обязательно должны увидеть Content-Type: application/vnd.ms-excel (для Excel) и заголовок Content-Disposition: attachment; filename=.... Если этих заголовков нет в ответе, который получает 1С, значит, мы стучимся «не в ту дверь» или с неверными параметрами.
Разберем разницу в подходах. Многие веб-серверы позволяют передавать параметры в строке запроса (GET), но для запуска тяжелых отчетов предпочитают POST. Если в браузере при нажатии кнопки «Пуск» метод меняется на POST, в 1С нам необходимо использовать метод ОтправитьДляОбработки() вместо Получить().
Посмотрим на пример реализации POST-запроса в 1С:
// Определяем параметры подключения
СерверИсточник = "sait2";
ПутьНаСервере = "/pls/info/REESTR_PERSONS_TO_1C.run";
ПараметрыЗапроса = "rep_user=IVANOV&p_com=30274&p_reestr_format=xls&p_action=Start";
// Создаем соединение
НТТР = Новый HTTPСоединение(СерверИсточник);
// Формируем запрос
// Параметры можно передать как в строке адреса, так и в теле запроса
Запрос = Новый HTTPЗапрос(ПутьНаСервере + "?" + ПараметрыЗапроса);
// Устанавливаем заголовки, чтобы сервер принял нас за браузер
Запрос.Заголовки.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
Запрос.Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
// Отправляем запрос и получаем ответ
ИмяФайлаРезультата = "C:\Reports\Report.xls";
Ответ = НТТР.ОтправитьДляОбработки(Запрос, ИмяФайлаРезультата);
Если Ответ.КодСостояния = 200 Тогда
Сообщить("Файл успешно сформирован и сохранен.");
Иначе
Сообщить("Ошибка сервера: " + Ответ.КодСостояния);
КонецЕсли;
Проанализируем одну из самых коварных проблем — использование кириллицы в параметрах URL. В исходном вопросе фигурировал параметр p_action=Пуск. При передаче такого запроса из 1С может возникнуть конфликт кодировок. 1С работает с UTF-8, а старые серверы Oracle (Apache 1.3 и подобные) часто ожидают Windows-1251 или вовсе некорректно обрабатывают спецсимволы.
Практический совет: если есть возможность изменить серверную часть, замените кириллические команды на латинские (например, «Пуск» на «Start»). Если такой возможности нет, обязательно используйте функцию КодироватьСтроку() для каждого параметра:
ДействиеКодированное = КодироватьСтроку("Пуск", СпособКодированияСтроки.URLКодирование);
Адрес = "/pls/info/REESTR_PERSONS_TO_1C.run?p_action=" + ДействиеКодированное;
Как показала практика обсуждения, именно смена «Пуск» на «Start» и приведение параметров к латинице часто является ключом к тому, чтобы сервер перестал отдавать форму и начал отдавать файл.
Рассмотрим ситуацию, когда файл передается в теле ответа. Если метод Получить(Запрос, ИмяФайла) по каким-то причинам не записывает данные на диск (например, если сервер возвращает специфический код состояния), мы можем получить данные в память и записать их вручную. Проанализируем пример использования ДвоичныеДанные:
Ответ = НТТР.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
// Получаем содержимое ответа
ДанныеФайла = Ответ.ПолучитьТелоКакДвоичныеДанные();
// Проверяем, что это не пустой файл и не HTML
РазмерДанных = ДанныеФайла.Размер();
Если РазмерДанных > 1000 Тогда // Условная проверка, что пришел отчет, а не маленькая форма
ДанныеФайла.Записаться(ИмяВходящегоФайла);
Сообщить("Файл записан, размер: " + РазмерДанных);
КонецЕсли;
КонецЕсли;
При работе с HTTP-запросами в 1С важно учитывать еще несколько технических моментов, которые могут влиять на результат:
HTTPСоединение, иначе 1С разорвет связь до того, как файл будет сформирован. Например: Новый HTTPСоединение(Сервер, , , , , 120) для ожидания в течение 2 минут.HTTPСоединение, либо через заголовок Authorization.Set-Cookie и передать их в последующем запросе на получение файла.Ответ.Заголовки.Получить("Content-Type"). Если там написано text/html, значит сервер вернул ошибку или форму, даже если код состояния 200. Если application/vnd.ms-excel — вы получили файл.Подводя итог, можно сказать, что решение проблемы «получения формы вместо файла» заключается в тщательной имитации поведения браузера. Использование метода POST, корректная URL-кодировка параметров и установка правильных заголовков позволяют успешно автоматизировать получение любых отчетов из внешних систем в 1С.