Как программно скачать файл из интернета по протоколу HTTP или HTTPS в 1С

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

В процессе разработки в среде 1С:Предприятие 8 часто возникает необходимость автоматизировать получение данных из внешних источников: прайс-листов поставщиков, курсов валют, классификаторов или обновлений. Одной из наиболее распространенных задач является скачивание файла по ссылке. На первый взгляд задача кажется простой, но на практике программисты сталкиваются с "невидимыми" ссылками, защищенными соединениями (SSL), блокировками со стороны серверов и проблемами определения расширения файла. В этой статье мы подробно разберем все этапы реализации этой задачи, от поиска прямой ссылки до обработки ответов сервера.

Поиск реального адреса файла

Прежде чем писать код, необходимо убедиться, что у нас есть прямая ссылка на файл. Часто на сайтах ссылка ведет не на сам документ, а на скрипт-обработчик (например, download.php?id=123) или на промежуточную страницу. Если использовать такую ссылку в методе КопироватьФайл, программа может скачать HTML-код страницы вместо ожидаемого архива или таблицы Excel.

Для определения реального расположения файла выполним следующие шаги:

  1. Откроем браузер (например, Firefox или Chrome) и перейдем на страницу загрузки.
  2. Нажмем правой кнопкой мыши на кнопке или ссылке "Скачать" и выберем пункт "Исследовать элемент".
  3. В открывшейся панели инструментов разработчика перейдем на вкладку "Сеть" (Network).
  4. Нажмем на ссылку скачивания на сайте.
  5. В списке запросов в консоли браузера найдем тот, который инициировал загрузку файла. В колонке "Заголовки" (Headers) мы увидим полный URL-адрес. Именно этот адрес нужно использовать в 1С.

Метод 1: Использование функции КопироватьФайл

Это самый простой способ, который подходит для прямых публичных ссылок, не требующих авторизации или специальных заголовков. Рассмотрим пример кода:


ИмяФайлаИсточника = "https://example.com/files/price.xlsx";
ИмяФайлаПриемника = "C:\Temp\price.xlsx";

Попытка
    КопироватьФайл(ИмяФайлаИсточника, ИмяФайлаПриемника);
    Сообщить("Файл успешно скачан!");
Исключение
    Сообщить("Ошибка при скачивании: " + ОписаниеОшибки());
КонецПопытки;

Важно помнить, что КопироватьФайл работает в синхронном режиме и блокирует поток выполнения до завершения операции. Если файл большой, интерфейс программы может "зависнуть".

Метод 2: Использование объекта HTTPСоединение

Для более гибкого управления процессом скачивания (например, когда нужно работать с HTTPS, передавать заголовки или анализировать ошибки сервера) следует использовать объект HTTPСоединение. Проанализируем стандартную ситуацию скачивания файла с сайта Центрального Банка или любого другого ресурса.


// Определяем параметры сервера и путь к файлу
Сервер = "www.cbr.ru";
ПутьНаСервере = "/print.asp?file=/statistics/credit_statistics/refinancing_rates.htm";

// Указываем локальный путь для сохранения
ПутьКЛокальномуФайлу = КаталогВременныхФайлов() + "rates.htm";

// Создаем соединение
НТТР = Новый HTTPСоединение(Сервер);

Попытка
    // Выполняем получение файла
    НТТР.Получить(ПутьНаСервере, ПутьКЛокальномуФайлу);
    ВходящийФайл = Новый Файл(ПутьКЛокальномуФайлу);
    Если ВходящийФайл.Существует() Тогда
        Сообщить("Файл получен, размер: " + ВходящийФайл.Размер());
    КонецЕсли;
Исключение
    Сообщить("Не удалось соединиться с сервером");
КонецПопытки;

Работа с защищенным соединением (HTTPS)

Современные сайты практически повсеместно используют протокол HTTPS. В 1С для работы с защищенным соединением необходимо использовать объект ЗащищенноеСоединениеOpenSSL. Рассмотрим пример для скачивания XML-прайса с защищенного ресурса:


ИнтернетАдрес = "www.example-shop.com";
ИмяФайлаНаСервере = "/upload/price.xml";
ЛокальныйПуть = "C:\Downloads\price.xml";

// Инициализируем защищенное соединение
// Используем стандартные настройки сертификатов ОС
SSL = Новый ЗащищенноеСоединениеOpenSSL();

// Создаем соединение на порту 443
Соединение = Новый HTTPСоединение(ИнтернетАдрес, 443, , , , , SSL);

// Формируем запрос
Запрос = Новый HTTPЗапрос(ИмяФайлаНаСервере);

Попытка
    Ответ = Соединение.Получить(Запрос, ЛокальныйПуть);
    
    // Проверяем код состояния (200 - успех)
    Если Ответ.КодСостояния = 200 Тогда
        Сообщить("Загрузка завершена успешно");
    Иначе
        Сообщить("Сервер вернул ошибку: " + Ответ.КодСостояния);
    КонецЕсли;
Исключение
    Сообщить("Произошла сетевая ошибка при обращении к " + ИнтернетАдрес);
КонецПопытки;

Решение проблемы "Файл размером 1 Кб"

Если после скачивания вы обнаружили, что файл весит всего 1 Кб и не открывается, скорее всего, сервер заблокировал запрос от 1С. Многие серверы проверяют заголовок User-Agent, чтобы отсекать автоматических ботов. Если этот заголовок не заполнен, сервер может отдать страницу с ошибкой (например, "403 Forbidden") вместо файла.

Разберем, как имитировать запрос от обычного браузера:


Запрос = Новый HTTPЗапрос(ИмяФайлаНаСервере);
// Устанавливаем заголовок, имитирующий браузер Chrome
Запрос.Заголовки.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");

Ответ = Соединение.Получить(Запрос, ЛокальныйПуть);

Также размер в 1 Кб может указывать на то, что скачанный файл является текстовым сообщением об ошибке. Попробуйте открыть такой файл обычным "Блокнотом" (Notepad++) — часто внутри содержится текст ошибки в формате HTML или JSON, который поможет понять причину отказа.

Как определить расширение файла, если оно неизвестно?

Бывают ситуации, когда ссылка не содержит расширения (например, api/get_report?id=500). В этом случае мы не знаем заранее, скачивается ли .zip, .xlsx или .pdf. Выясним, как получить эту информацию программно.

Для этого необходимо проанализировать заголовки HTTP-ответа, которые возвращает сервер. Нас интересуют два заголовка: Content-Type (тип контента) и Content-Disposition (часто содержит имя файла).


Ответ = Соединение.Получить(Запрос); // Получаем данные в память без записи в файл
Если Ответ.КодСостояния = 200 Тогда
    // 1. Попытаемся найти имя файла в заголовке Content-Disposition
    ДанныеЗаголовка = Ответ.Заголовки.Получить("Content-Disposition");
    // Пример значения: attachment; filename="report_2023.zip"
    
    // 2. Или определим тип по Content-Type
    ТипКонтента = Ответ.Заголовки.Получить("Content-Type");
    // Если ТипКонтента = "application/zip", значит это архив.
    
    // Сохраняем данные из тела ответа
    ДвоичныеДанные = Ответ.ПолучитьТелоКакДвоичныеДанные();
    ДвоичныеДанные.Записать(ПутьДляСохранения);
КонецЕсли;

Дополнительные рекомендации

Рассмотрим еще несколько важных моментов, которые помогут сделать ваш код более надежным:

Используя предложенные методы, вы сможете настроить стабильную загрузку файлов в 1С из любых внешних источников, обеспечив корректную обработку защищенных протоколов и различных типов данных.

← На главную