Как загрузить фото по ссылке HTTP и победить ошибку 301 Moved Permanently в 1С

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

При разработке механизмов интеграции, например, при загрузке каталогов товаров из YML-файлов, программисты часто сталкиваются с ситуацией, когда прямая ссылка на изображение, открывающаяся в браузере, отказывается скачиваться средствами 1С. Вместо ожидаемого бинарного файла картинки в текстовый лог или файл-результат записывается HTML-код с заголовком 301 Moved Permanently. Разберем подробно, почему это происходит и какими способами можно гарантированно получить файл в систему.

Анализ причины ошибки: почему 1С получает текст вместо картинки

Прежде всего, проанализируем ситуацию. Код состояния HTTP 301 означает, что запрашиваемый ресурс был окончательно перемещен на новый адрес. В современных веб-реалиях это чаще всего связано с принудительным перенаправлением с незащищенного протокола http на защищенный https. Веб-сервер (например, nginx) настроен таким образом, что при попытке обращения по порту 80 он отдает браузеру или программному клиенту заголовок с новым адресом.

Стандартный объект 1С HTTPСоединение не умеет автоматически переходить по редиректам «в один клик», если не заданы правильные настройки соединения. В результате вместо скачивания файла 1С просто сохраняет тело ответа сервера, которое содержит информационную HTML-страницу о перемещении ресурса.

Решение 1: Использование HTTPСоединение с поддержкой SSL

Наиболее правильный и гибкий способ — это использование объекта HTTPСоединение с явным указанием защищенного соединения. Рассмотрим, как правильно модифицировать код, чтобы 1С могла работать с HTTPS-ссылками.

Для работы с защищенным протоколом нам понадобится объект ЗащищенноеСоединениеOpenSSL. Проанализируем пример кода, который позволяет успешно скачать файл с сервера, требующего HTTPS:


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

// Создаем соединение. Обратите внимание, что протокол в адресе не указывается, 
// только доменное имя. 
Соединение = Новый HTTPСоединение("www.stolline.ru", , , , , , Защита);

// Формируем запрос к конкретному файлу
Запрос = Новый HTTPЗапрос("/upload/photos/nahodka/catalog_180012005500100030144_2.jpg"); 

// Получаем ответ и сохраняем его в локальный файл
Попытка
    Ответ = Соединение.Получить(Запрос, "d:\temp\1112.jpg");
    Если Ответ.КодСостояния = 200 Тогда
        Сообщить("Файл успешно загружен!");
    Иначе
        Сообщить("Ошибка сервера: " + Ответ.КодСостояния);
    КонецЕсли;
Исключение
    Сообщить("Ошибка связи: " + ОписаниеОшибки());
КонецПопытки;

В данном примере крайне важно, чтобы в конструкторе HTTPСоединение седьмым параметром был передан объект защиты. Без него 1С попытается подключиться по стандартному 80-му порту, и вы снова получите ошибку 301.

Решение 2: Использование метода КопироватьФайл

Существует более простой, «быстрый» способ загрузки файлов из интернета, который часто используется в простых обработках. Метод КопироватьФайл в платформе 1С поддерживает работу с URL-адресами в качестве источника. Однако здесь есть важный нюанс, который мы сейчас разберем.

Если вы используете метод ПереместитьФайл для URL, сервер может вернуть ошибку 405 Method Not Allowed. Это происходит потому, что «перемещение» подразумевает удаление файла из источника после копирования (HTTP метод DELETE), что запрещено для публичных ресурсов. Поэтому необходимо использовать именно КопироватьФайл.

Рассмотрим пример правильного использования:


Источник = "https://www.stolline.ru/upload/photos/nahodka/catalog_180012005500100030144_2.jpg";
Приемник = "d:\temp\1112.jpg";

Попытка
    КопироватьФайл(Источник, Приемник);
    Сообщить("Копирование завершено.");
Исключение
    // Если ссылка содержит http, а сервер требует https, 
    // данный метод может отработать некорректно без явного указания протокола в строке
    Сообщить("Не удалось скачать файл: " + ОписаниеОшибки());
КонецПопытки;

Важный совет: Чтобы избежать проблем с редиректами при использовании этого метода, рекомендуется заранее проверять строку адреса и, если она начинается с http://, программно заменять её на https://.

Дополнительные технические нюансы для стабильной работы

Проанализируем ситуации, когда даже правильный код может дать сбой, и выясним, как их предотвратить:

  1. Заголовок User-Agent: Многие современные сервера (особенно под управлением nginx) блокируют запросы, которые не идентифицируют себя как браузер. Чтобы избежать этого, добавьте в HTTPЗапрос соответствующий заголовок: Запрос.Заголовки.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");.
  2. Проверка типа контента: После получения ответа от сервера через HTTPСоединение, всегда проверяйте заголовок Content-Type. Если сервер вернул image/jpeg — вы получили картинку. Если text/html — скорее всего, вы скачали страницу с ошибкой.
  3. Автоматическая обработка редиректов: Если вы не знаете заранее, будет ли редирект, можно написать функцию, которая анализирует Ответ.КодСостояния. Если он равен 301 или 302, нужно извлечь из Ответ.Заголовки параметр Location и повторить запрос по новому адресу.

Итоги

Мы разобрали, что основной причиной проблемы «загрузки текста вместо фото» является политика безопасности веб-серверов, перенаправляющая трафик на HTTPS. Для надежного решения задачи в 1С:

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

← На главную