Часто при интеграции 1С с внешними торговыми площадками или государственными порталами разработчики сталкиваются с ситуацией, когда стандартные методы платформы, такие как ПолучениеФайловИзИнтернета.СкачатьФайлВоВременноеХранилище или простая команда ЗапуститьПриложение, не позволяют корректно получить файл для дальнейшей обработки. Проблема усугубляется тем, что в браузере файл скачивается мгновенно, а при попытке сделать это из кода 1С сервер возвращает пустые данные, ошибку 406 Not Acceptable или бесконечные перенаправления (редиректы).
В этой статье мы подробно разберем, как реализовать надежный механизм скачивания файлов, проанализируем причины возникновения ошибок и научимся правильно настраивать HTTP-запросы, чтобы сервер принимал нашу информационную базу за легитимного пользователя.
Стандартные процедуры БСП (Библиотеки стандартных подсистем) спроектированы для работы с "чистыми" ссылками на статические файлы. Однако современные порталы, такие как магазин НЛМК, используют динамическую генерацию ссылок и многоуровневую защиту. Проанализируем основные причины неудач:
nginx или балансировщики типа Citrix NetScaler) видят заголовок User-Agent, который 1С отправляет по умолчанию ("1C+Enterprise/8.3"). Многие системы безопасности блокируют такие запросы, считая их попыткой несанкционированного парсинга данных.Cookies, данные об авторизации и страницу-источник (Referer). Платформа 1С при создании нового HTTPСоединение начинает запрос "с чистого листа", что ведет к потере прав доступа.Для начала откажемся от простых команд и перейдем к использованию низкоуровневых объектов платформы. Разберем создание соединения с использованием защищенного протокола SSL, так как большинство современных ресурсов работают через HTTPS.
Рассмотрим пример кода для инициализации соединения:
ИмяСервера = "doc.nlmk.shop";
Таймаут = 60; // Увеличим таймаут для больших файлов
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
HTTPСоединение = Новый HTTPСоединение(ИмяСервера, , , , , Таймаут, ЗащищенноеСоединение);
Важный нюанс: Обратите внимание, что мы передаем только доменное имя сервера без префикса https://. Весь путь к файлу будет указываться отдельно в объекте запроса.
Проанализируем ситуацию, когда сервер возвращает код 302. В этом случае в заголовках ответа будет содержаться параметр Location, указывающий на новый адрес. Выясним, как программно "пройти" по этой цепочке.
Ресурс = "/api/v1/views/certificates/17jT47KKpj9Y4Aq/scans";
Запрос = Новый HTTPЗапрос(Ресурс);
Ответ = HTTPСоединение.Получить(Запрос);
Если Ответ.КодСостояния >= 300 И Ответ.КодСостояния < 400 Тогда
// Сервер просит перейти по другому адресу
НовыйАдрес = Ответ.Заголовки.Получить("Location");
Если НовыйАдрес <> Неопределено Тогда
// Здесь важно проверить, является ли адрес полным или относительным
// Если адрес содержит домен, нужно пересоздать соединение
// Если адрес относительный (начинается с /), используем текущее
Сообщить("Выполняю переход по адресу: " + НовыйАдрес);
// Повторный запрос по новому адресу
ЗапросРедиректа = Новый HTTPЗапрос(НовыйАдрес);
Ответ = HTTPСоединение.Получить(ЗапросРедиректа);
КонецЕсли;
КонецЕсли;
Однако, как показывает практика обсуждения в теме, иногда редирект может вести на страницу ошибки (например, /error/406). Это происходит из-за того, что сервер "не узнал" клиента. Чтобы этого избежать, перейдем к настройке заголовков.
Чтобы сервер отдал файл, мы должны выглядеть как обычный пользователь. Проанализируем ключевые заголовки, которые необходимо добавить в HTTPЗапрос:
application/pdf).Доработаем наш код:
Запрос = Новый 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Соединение.Получить(Запрос);
В сообщениях форума упоминается наличие куки NSC_ESNS. Это признак работы балансировщика нагрузки. Чтобы получить файл, иногда требуется выполнить "прогревочный" запрос к главной странице сайта, чтобы сервер установил сессию, а затем передать полученные куки в основной запрос.
Рассмотрим алгоритм работы с куками:
Set-Cookie.Cookie последующих запросов.
// 1. Получаем сессионные данные
ЗапросПрогрев = Новый HTTPЗапрос("/");
ОтветПрогрев = HTTPСоединение.Получить(ЗапросПрогрев);
СтрокаКуки = "";
Для Каждого Заголовок Из ОтветПрогрев.Заголовки Цикл
Если ВРег(Заголовок.Ключ) = "SET-COOKIE" Тогда
// Извлекаем значение до первой точки с запятой
ЧастьКуки = Лев(Заголовок.Значение, Найти(Заголовок.Значение, ";"));
СтрокаКуки = СтрокаКуки + ЧастьКуки + " ";
КонецЕсли;
КонецЦикла;
// 2. Используем куки для скачивания файла
ЗапросФайла = Новый HTTPЗапрос(Ресурс);
ЗапросФайла.Заголовки.Вставить("Cookie", СокрЛП(СтрокаКуки));
ЗапросФайла.Заголовки.Вставить("User-Agent", "Mozilla/5.0...");
ОтветФайла = HTTPСоединение.Получить(ЗапросФайла);
Если код состояния ответа равен 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-протокола.