Как программно скачать и обработать файлы из 1С, если прямая ссылка ведет на редирект или выдает ошибку?

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

Часто при интеграции 1С с внешними торговыми площадками или государственными порталами разработчики сталкиваются с ситуацией, когда стандартные методы платформы, такие как ПолучениеФайловИзИнтернета.СкачатьФайлВоВременноеХранилище или простая команда ЗапуститьПриложение, не позволяют корректно получить файл для дальнейшей обработки. Проблема усугубляется тем, что в браузере файл скачивается мгновенно, а при попытке сделать это из кода 1С сервер возвращает пустые данные, ошибку 406 Not Acceptable или бесконечные перенаправления (редиректы).

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

Почему стандартные методы 1С часто оказываются бессильны?

Стандартные процедуры БСП (Библиотеки стандартных подсистем) спроектированы для работы с "чистыми" ссылками на статические файлы. Однако современные порталы, такие как магазин НЛМК, используют динамическую генерацию ссылок и многоуровневую защиту. Проанализируем основные причины неудач:

  1. Защита от ботов: Веб-серверы (часто это nginx или балансировщики типа Citrix NetScaler) видят заголовок User-Agent, который 1С отправляет по умолчанию ("1C+Enterprise/8.3"). Многие системы безопасности блокируют такие запросы, считая их попыткой несанкционированного парсинга данных.
  2. Отсутствие контекста сессии: Браузер при скачивании передает накопленные файлы Cookies, данные об авторизации и страницу-источник (Referer). Платформа 1С при создании нового HTTPСоединение начинает запрос "с чистого листа", что ведет к потере прав доступа.
  3. Редиректы (Код 302): Ссылка может вести не на сам файл, а на скрипт, который проверяет права пользователя и перенаправляет его на временный адрес хранилища. Если не обработать код состояния 302 Found вручную, мы получим лишь техническую страницу вместо PDF-документа.

Шаг 1. Настройка базового HTTP-соединения

Для начала откажемся от простых команд и перейдем к использованию низкоуровневых объектов платформы. Разберем создание соединения с использованием защищенного протокола SSL, так как большинство современных ресурсов работают через HTTPS.

Рассмотрим пример кода для инициализации соединения:


ИмяСервера = "doc.nlmk.shop";
Таймаут = 60; // Увеличим таймаут для больших файлов
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();

HTTPСоединение = Новый HTTPСоединение(ИмяСервера, , , , , Таймаут, ЗащищенноеСоединение);

Важный нюанс: Обратите внимание, что мы передаем только доменное имя сервера без префикса https://. Весь путь к файлу будет указываться отдельно в объекте запроса.

Шаг 2. Обработка редиректов и получение прямой ссылки

Проанализируем ситуацию, когда сервер возвращает код 302. В этом случае в заголовках ответа будет содержаться параметр Location, указывающий на новый адрес. Выясним, как программно "пройти" по этой цепочке.


Ресурс = "/api/v1/views/certificates/17jT47KKpj9Y4Aq/scans";
Запрос = Новый HTTPЗапрос(Ресурс);

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

Если Ответ.КодСостояния >= 300 И Ответ.КодСостояния < 400 Тогда
    // Сервер просит перейти по другому адресу
    НовыйАдрес = Ответ.Заголовки.Получить("Location");
    Если НовыйАдрес <> Неопределено Тогда
        // Здесь важно проверить, является ли адрес полным или относительным
        // Если адрес содержит домен, нужно пересоздать соединение
        // Если адрес относительный (начинается с /), используем текущее
        Сообщить("Выполняю переход по адресу: " + НовыйАдрес);
        
        // Повторный запрос по новому адресу
        ЗапросРедиректа = Новый HTTPЗапрос(НовыйАдрес);
        Ответ = HTTPСоединение.Получить(ЗапросРедиректа);
    КонецЕсли;
КонецЕсли;

Однако, как показывает практика обсуждения в теме, иногда редирект может вести на страницу ошибки (например, /error/406). Это происходит из-за того, что сервер "не узнал" клиента. Чтобы этого избежать, перейдем к настройке заголовков.

Шаг 3. Эмуляция браузера через заголовки запроса

Чтобы сервер отдал файл, мы должны выглядеть как обычный пользователь. Проанализируем ключевые заголовки, которые необходимо добавить в HTTPЗапрос:

Доработаем наш код:


Запрос = Новый HTTPЗапрос(Ресурс);
Запрос.Заголовки.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36");
Запрос.Заголовки.Вставить("Accept", "application/pdf, application/octet-stream, */*");
Запрос.Заголовки.Вставить("Referer", "https://doc.nlmk.shop/");

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

Шаг 4. Работа с сессиями и Cookies

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

Рассмотрим алгоритм работы с куками:

  1. Выполняем запрос к главной странице.
  2. Извлекаем заголовки Set-Cookie.
  3. Формируем из них строку для заголовка Cookie последующих запросов.

// 1. Получаем сессионные данные
ЗапросПрогрев = Новый HTTPЗапрос("/");
ОтветПрогрев = HTTPСоединение.Получить(ЗапросПрогрев);

СтрокаКуки = "";
Для Каждого Заголовок Из ОтветПрогрев.Заголовки Цикл
    Если ВРег(Заголовок.Ключ) = "SET-COOKIE" Тогда
        // Извлекаем значение до первой точки с запятой
        ЧастьКуки = Лев(Заголовок.Значение, Найти(Заголовок.Значение, ";"));
        СтрокаКуки = СтрокаКуки + ЧастьКуки + " ";
    КонецЕсли;
КонецЦикла;

// 2. Используем куки для скачивания файла
ЗапросФайла = Новый HTTPЗапрос(Ресурс);
ЗапросФайла.Заголовки.Вставить("Cookie", СокрЛП(СтрокаКуки));
ЗапросФайла.Заголовки.Вставить("User-Agent", "Mozilla/5.0...");

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

Шаг 5. Сохранение и проверка результата

Если код состояния ответа равен 200 (OK), мы можем приступать к записи файла на диск. Проанализируем, как правильно сохранить бинарные данные, полученные от сервера.


Если ОтветФайла.КодСостояния = 200 Тогда
    ДанныеФайла = ОтветФайла.ПолучитьТелоКакДвоичныеДанные();
    
    // Определим имя файла. Его можно взять из заголовка Content-Disposition
    ИмяФайла = "certificate.pdf";
    ЗаголовокДиспозиция = ОтветФайла.Заголовки.Получить("Content-Disposition");
    Если ЗаголовокДиспозиция <> Неопределено Тогда
        // Здесь можно распарсить строку "attachment; filename=..."
    КонецЕсли;
    
    ПутьСохранения = "D:\Files\" + ИмяФайла;
    ДанныеФайла.Записать(ПутьСохранения);
    Сообщить("Файл успешно сохранен: " + ПутьСохранения);
Иначе
    Сообщить("Ошибка при скачивании! Код: " + ОтветФайла.КодСостояния);
    Сообщить("Текст ответа: " + ОтветФайла.ПолучитьТелоКакСтроку());
КонецЕсли;

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

Проанализировав ситуацию с нестабильностью скачивания (когда файл отдается через раз), можно выделить несколько советов:

Использование пауз: Если сервер генерирует файл "на лету", после первого запроса может потребоваться пауза в 1-2 секунды (Приостановить(2)), прежде чем выполнять повторный запрос по адресу редиректа.

Проверка TLS: Убедитесь, что ваша операционная система и версия платформы 1С поддерживают современные протоколы шифрования (TLS 1.2 и выше). В старых релизах 8.3.10 и ниже могут возникать ошибки установки защищенного соединения, которые лечатся обновлением платформы или использованием внешних библиотек (например, curl или WinHttp через COM-объект).

Анализ в браузере: Если код всё равно не работает, откройте консоль разработчика в браузере (F12), перейдите на вкладку Network и выполните скачивание вручную. Проанализируйте каждый заголовок (Header), который отправляет ваш браузер, и постарайтесь максимально точно воспроизвести их в коде 1С.

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

← На главную