При интеграции 1С с внешними веб-сервисами и сайтами разработчики часто сталкиваются с ситуацией, когда при попытке скачать файл сохраняется не сам целевой документ (например, XML или ZIP), а HTML-страница с ошибкой 301 Moved Permanently или формой авторизации. Разберем по шагам причины такого поведения платформы и рассмотрим правильные варианты реализации загрузки файлов.
Код состояния HTTP 301 Moved Permanently означает, что запрашиваемый ресурс был окончательно перемещен на другой адрес. В платформе 1С объект HTTPСоединение по умолчанию не переходит по редиректам автоматически. Если сервер отправляет перенаправление, 1С добросовестно сохраняет тело ответа этого перенаправления в указанный файл на диске.
В веб-разработке и современных сервисах редирект 301 чаще всего возникает в двух случаях:
HTTPСоединение не инициализирован параметр защищенного соединения, платформа 1С стучится по HTTP и получает ответ 301.Если файл находится в публичном доступе, но доступен только по протоколу HTTPS, необходимо явно указать защищенный режим при создании объекта HTTPСоединение. Для этого используется объект ЗащищенноеСоединениеOpenSSL.
Рассмотрим пример правильного создания защищенного соединения и скачивания файла:
Сервер = "office7.auto.ru";
ПутьКФайлуНаСервере = "/v2/products/all/sales/upload/cars/help/get/";
ПутьДляСохранения = "C:\Temp\avtoru_help.zip";
// Инициализируем защищенное соединение для протокола HTTPS
Защита = Новый ЗащищенноеСоединениеOpenSSL();
// Передаем параметры: Сервер, Порт (443 для HTTPS), Логин, Пароль, Прокси, Таймаут, ЗащищенноеСоединение
Соединение = Новый HTTPСоединение(Сервер, 443, , , , 30, Защита);
// Выполняем GET-запрос и сохраняем файл
HTTPЗапрос = Новый HTTPЗапрос(ПутьКФайлуНаСервере);
Ответ = Соединение.Получить(HTTPЗапрос, ПутьДляСохранения);
Если Ответ.КодСостояния = 200 Тогда
// Файл успешно получен и сохранен на диск
Иначе
// Обрабатываем другие коды состояния (например, 404 или 403)
КонецЕсли;
Обратите внимание: указание порта 443 и передача объекта ЗащищенноеСоединениеOpenSSL исключают промежуточный редирект с незащищенного протокола, позволяя напрямую скачать файл.
Частая ошибка разработчиков — передача учетных данных сайта в параметры «Пользователь» и «Пароль» конструктора HTTPСоединение. Эти параметры предназначены исключительно для протокольной аутентификации HTTP Basic / Digest. Если веб-сайт использует стандартную веб-авторизацию с формами входа, такие параметры сервером игнорируются.
Для скачивания файлов с ресурсов, требующих веб-авторизации, необходимо реализовать двухэтапный процесс:
Set-Cookie.Cookie последующего GET-запроса на скачивание файла.Посмотрим на пример реализации работы с заголовками авторизации:
Защита = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение("office7.auto.ru", 443, , , , 30, Защита);
// Шаг 1. Формируем запрос авторизации (передаем тело и тип контента)
ЗапросАвторизации = Новый HTTPЗапрос("/auth/login");
ЗапросАвторизации.Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
ЗапросАвторизации.УстановитьТелоИзСтроки("login=my_user&password=my_password", "UTF-8");
ОтветАвторизации = Соединение.ОтправитьДляОбработки(ЗапросАвторизации);
// Извлекаем сессионную куку из ответа
Куки = "";
Если ОтветАвторизации.Заголовки.Свойство("Set-Cookie") Тогда
Куки = ОтветАвторизации.Заголовки.Получить("Set-Cookie");
КонецЕсли;
// Шаг 2. Запрашиваем закрытый файл с передачей сессии
ЗапросФайла = Новый HTTPЗапрос("/products/all/sales/upload/cars/catalog/");
Если ЗначениеЗаполнено(Куки) Тогда
ЗапросФайла.Заголовки.Вставить("Cookie", Куки);
КонецЕсли;
ПутьДляСохранения = "C:\Temp\avtoru_catalog.xml";
ОтветФайла = Соединение.Получить(ЗапросФайла, ПутьДляСохранения);
Если сервер возвращает коды перенаправления 301, 302, 307 или 308 по логике своей работы, платформе 1С необходимо явно обработать заголовок Location.
Разберем алгоритм ручной обработки редиректа:
Защита = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение("office7.auto.ru", 443, , , , 30, Защита);
ТекущийПуть = "/products/all/sales/upload/cars/catalog/";
ПутьДляСохранения = "C:\Temp\result.xml";
МаксРедиректов = 5;
Счетчик = 0;
Пока Счетчик < МаксРедиректов Цикл
HTTPЗапрос = Новый HTTPЗапрос(ТекущийПуть);
Ответ = Соединение.Получить(HTTPЗапрос, ПутьДляСохранения);
// Проверяем, вернул ли сервер код перенаправления
Если Ответ.КодСостояния = 301 ИЛИ Ответ.КодСостояния = 302 ИЛИ Ответ.КодСостояния = 307 Тогда
Если Ответ.Заголовки.Свойство("Location") Тогда
НовыйURL = Ответ.Заголовки.Получить("Location");
// Если перенаправление ведет на относительный путь
ТекущийПуть = НовыйURL;
Счетчик = Счетчик + 1;
Иначе
Прервать;
КонецЕсли;
ИначеЕсли Ответ.КодСостояния = 200 Тогда
// Файл успешно получен
Прервать;
Иначе
// Обработка ошибок сервера
Прервать;
КонецЕсли;
КонецЦикла;
Метод КопироватьФайл() можно применять исключительно для простой прямой загрузки общедоступных файлов по прямым ссылкам без авторизации и сложных редиректов. Данный метод не предоставляет доступа к управлению заголовками (таким как Cookie или Authorization), не позволяет задать таймауты и не возвращает детальные HTTP-коды при возникновении сетевых ошибок. Для надежного обмена данными в промышленных решениях рекомендуется всегда использовать объект HTTPСоединение.