В процессе интеграции 1С с внешними веб-сервисами и базами данных разработчики часто сталкиваются с необходимостью автоматического скачивания файлов (отчетов, прайс-листов, реестров). Часто в качестве рабочего примера предоставляется готовый код на других языках программирования, например, на C#. Перенос этой логики в 1С может вызвать определенные трудности, связанные со спецификой работы платформы 1С с HTTP-протоколом.
В этой статье мы подробно разберем, как перенести рабочий пример скачивания файла с C# в 1С. Мы проанализируем частые ошибки разработчиков, такие как путаница между параметрами URL и заголовками запроса, проблемы с кодированием кириллических символов и управление таймаутом соединения при длительной генерации файлов на стороне сервера. Также мы рассмотрим несколько способов реализации задачи — от простых однострочных команд до профессионального кроссплатформенного подхода.
Рассмотрим пример кода на C#, который выполняет скачивание файла:
private void button1_Click(object sender, EventArgs e)
{
WebClient webClient = new WebClient();
string link = @"http://dezvgr2/pls/info/REESTR_SOB_TO_1C.run?rep_user=TVERETINA&p_com=30274&p_reestr_format=xls&p_action=Start";
string downloadFileName = System.IO.Path.GetFileName("test.xls");
webClient.DownloadFile(new Uri(link), @"F:\tmp\test\" + downloadFileName);
}
Этот код выполняет классический GET-запрос по указанному URL-адресу. Параметры запроса (rep_user, p_com, p_reestr_format и p_action) передаются непосредственно в строке адреса (Query Parameters). На стороне веб-сервера (в данном случае это шлюз Oracle PL/SQL Gateway /pls/...) эти параметры обрабатываются, формируется отчет в формате XLS и отдается клиенту в виде бинарного потока. Наша задача — повторить это поведение в 1С.
Прежде чем перейти к рабочим решениям, разберем ключевые ошибки, из-за которых стандартные методы 1С могут возвращать пустую страницу с параметрами вместо целевого файла Excel.
HTTPЗапрос.Заголовки.Вставить(). Заголовки HTTP предназначены для метаданных (например, тип контента, авторизация, настройки кэширования). Параметры же отчета должны находиться в самой строке URL-запроса (для GET) или в теле запроса (для POST). Если передать их в заголовках, принимающий сервер их просто проигнорирует и вернет дефолтную страницу настроек.p_action=Пуск), сервер может их не понять из-за различий в кодировках (UTF-8, Windows-1251, ISO-8859-1). Символы кириллицы в строке URL должны быть обязательно закодированы по стандарту RFC 3986 (Percent-encoding).Теперь разберем проверенные способы реализации скачивания файла в 1С по шагам.
Использование встроенных объектов HTTPСоединение и HTTPЗапрос является стандартом современной разработки. Этот код будет стабильно работать как на Windows, так и на Linux-серверах, а также в веб-клиенте.
Выясним причину, почему в 1С нельзя просто передать полную ссылку в соединение. Дело в том, что конструктор HTTPСоединение принимает в качестве первого параметра только имя сервера (домен или IP-адрес), а сам путь к ресурсу и параметры запроса передаются в объект HTTPЗапрос.
Разберем готовый шаблон кода для скачивания файла:
// Определение путей и параметров запроса
СерверАдрес = "dezvgr2";
ИмяВходящегоФайла = "F:\tmp\test\test.xls";
// Формируем параметры запроса. Если есть русские буквы, обязательно кодируем их!
ПараметрДействия = КодироватьСтроку("Start", СпособКодированияСтроки.КодировкаURL);
ПараметрПользователя = КодироватьСтроку("TVERETINA", СпособКодированияСтроки.КодировкаURL);
// Собираем путь ресурса с параметрами
ПутьЗапроса = "/pls/info/REESTR_SOB_TO_1C.run"
+ "?rep_user=" + ПараметрПользователя
+ "&p_com=30274"
+ "&p_reestr_format=xls"
+ "&p_action=" + ПараметрДействия;
// Создаем HTTP-соединение.
// Шестым параметром устанавливаем таймаут ожидания сервера в секундах (например, 600 секунд = 10 минут)
// Это критически важно, если файл формируется долго!
Соединение = Новый HTTPСоединение(СерверАдрес, , , , , 600);
HTTPЗапрос = Новый HTTPЗапрос(ПутьЗапроса);
Попытка
// Отправляем GET-запрос на сервер
HTTPОтвет = Соединение.Получить(HTTPЗапрос);
Если HTTPОтвет.КодСостояния = 200 Тогда
// Получаем двоичные данные из тела ответа и записываем их в файл
ДвоичныеДанныеФайла = HTTPОтвет.ПолучитьТелоКакДвоичныеДанные();
ДвоичныеДанныеФайла.Записать(ИмяВходящегоФайла);
Сообщить("Файл успешно скачан и сохранен: " + ИмяВходящегоФайла);
Иначе
Сообщить("Ошибка сервера! Код состояния: " + HTTPОтвет.КодСостояния);
Сообщить("Ответ сервера: " + HTTPОтвет.ПолучитьТелоКакСтроку());
КонецЕсли;
Исключение
Сообщить("Не удалось установить соединение с сервером: " + ОписаниеОшибки());
КонецПопытки;
В этом примере мы использовали метод Получить() для отправки классического GET-запроса. Если принимающий веб-сервер требует передачи параметров методом POST, мы можем использовать метод ОтправитьДляОбработки(), передав параметры в теле запроса, либо оставить параметры в строке запроса в зависимости от требований API сервера.
Если вам не требуется тонкая настройка заголовков, авторизации или таймаутов, а нужно просто "скачать файл по ссылке как в браузере", можно воспользоваться глобальным методом платформы КопироватьФайл. Данный метод поддерживает схемы адресации http и https.
Посмотрим на пример его использования:
СсылкаНаФайл = "http://dezvgr2/pls/info/REESTR_SOB_TO_1C.run?rep_user=TVERETINA&p_com=30274&p_reestr_format=xls&p_action=Start";
ПутьСохранения = "F:\tmp\test\test.xls";
Попытка
// Платформа сама установит HTTP-соединение, отправит GET-запрос и сохранит результат на диск
КопироватьФайл(СсылкаНаФайл, ПутьСохранения);
Сообщить("Файл успешно скопирован.");
Исключение
Сообщить("Произошла ошибка при копировании файла: " + ОписаниеОшибки());
КонецПопытки;
Важное примечание: при использовании этого метода в адресах необходимо указывать только прямые слеши (/), а не обратные (\). На веб-клиенте этот метод работает только с локальными файлами и требует предварительного подключения расширения работы с файлами.
В старых конфигурациях или специфических сценариях администрирования на Windows-платформах разработчики часто используют компоненты операционной системы через механизм COM-соединения. Для этого подходят объекты WinHttp.WinHttpRequest.5.1 и ADODB.Stream.
Рассмотрим, как это выглядит в коде 1С:
ИмяВходящегоФайла = "F:\tmp\test\test.xls";
Ссылка = "http://dezvgr2/pls/info/REESTR_SOB_TO_1C.run?rep_user=TVERETINA&p_com=30274&p_reestr_format=xls&p_action=Start";
Попытка
// Инициализация WinHTTP запроса
WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
WinHttp.Open("GET", Ссылка, Ложь); // Ложь указывает на синхронный режим ожидания
WinHttp.Send();
Если WinHttp.Status = 200 Тогда
// Запись бинарного потока ответа на диск через ADODB.Stream
Stream = Новый COMОбъект("ADODB.Stream");
Stream.Type = 1; // Binary data
Stream.Mode = 3; // Read/Write
Stream.Open();
Stream.Write(WinHttp.ResponseBody);
Stream.SaveToFile(ИмяВходящегоФайла, 2); // 2 - перезаписывать существующий файл
Stream.Close();
Сообщить("Файл успешно сохранен через COM.");
Иначе
Сообщить("Ошибка HTTP: " + WinHttp.Status + " " + WinHttp.StatusText);
КонецЕсли;
Исключение
Сообщить("Ошибка при работе с COM-объектами: " + ОписаниеОшибки());
КонецПопытки;
Предупреждение: Мы настоятельно рекомендуем избегать использования COM-объектов в современном коде 1С. Такой код не запустится, если ваша база 1С будет перенесена на сервер под управлением Linux, а также вызовет сложности при переходе на новые версии платформы.
Для реализации скачивания файлов по HTTP-ссылкам в 1С всегда отдавайте предпочтение Способу 1 (HTTPСоединение). Он обеспечивает:
При передаче строковых параметров на русском языке не забывайте использовать функцию КодироватьСтроку, чтобы избежать искажения данных на веб-сервере.