Загрузить содержимое из интернет. Загружает содержимое из Интернет по протоколу HTTP(S)
// Загружает содержимое из Интернет по протоколу HTTP(S)
// с использованием методов GET, POST или PUT.
//
Функция ЗагрузитьСодержимоеИзИнтернет(
Знач URL,
Знач Логин = Неопределено,
Знач Пароль = Неопределено,
ДопПараметры = Неопределено) Экспорт
Результат = Новый Структура;
Результат.Вставить("КодОшибки" , "");
Результат.Вставить("СообщениеОбОшибке" , "");
Результат.Вставить("ИнформацияОбОшибке", "");
Результат.Вставить("Содержимое" , Неопределено);
Результат.Вставить("КодСостояния" , 0);
Результат.Вставить("ФорматОтвета" , 0);
// Формат ответа: 0 - имя файла ответа, 1 - как строка, 2 - как двоичные данные.
// Метод: "GET", "POST" или "PUT".
// ДанныеДляОбработки: данные, передаваемые методом POST.
// ФорматДанныхДляОбработки: 0 - имя файла, 1 как строка, 2 - как двоичные данные.
// Заголовки - заголовки запроса.
ПараметрыПолучения = Новый Структура;
ПараметрыПолучения.Вставить("ФорматОтвета" , 0);
ПараметрыПолучения.Вставить("Метод" , "GET");
ПараметрыПолучения.Вставить("ДанныеДляОбработки" , Неопределено);
ПараметрыПолучения.Вставить("ФорматДанныхДляОбработки", 0);
ПараметрыПолучения.Вставить("Заголовки" , Неопределено);
ПараметрыПолучения.Вставить("ИмяФайлаОтвета" , Неопределено);
ПараметрыПолучения.Вставить("Таймаут" , -1);
ПараметрыПолучения.Вставить("НастройкиПрокси" , Неопределено);
Если ДопПараметры <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(ПараметрыПолучения, ДопПараметры);
КонецЕсли;
Если ПараметрыПолучения.Таймаут = -1 Тогда
// Таймаут по умолчанию.
ПараметрыПолучения.Таймаут = 30;
КонецЕсли;
Результат.ФорматОтвета = ПараметрыПолучения.ФорматОтвета;
КоличествоПеренаправлений = 0;
МаксКолвоПеренаправлений = 7;
Перенаправления = Новый Массив;
ВыполненныеПеренаправления = Новый Соответствие;
ПроксиПоСхемам = Новый Соответствие;
ЗащищенноеСоединениеКэш = Неопределено;
URLДляПолучения = URL;
HTTPЗапрос = Новый HTTPЗапрос;
Если ПараметрыПолучения.Заголовки <> Неопределено Тогда
HTTPЗапрос.Заголовки = ПараметрыПолучения.Заголовки;
КонецЕсли;
ТелоУстановлено = Ложь;
Ответ = Неопределено;
Пока КоличествоПеренаправлений < МаксКолвоПеренаправлений Цикл
СтруктураURI = ОбщегоНазначенияКлиентСервер.СтруктураURI(URLДляПолучения);
Если СтруктураURI.Схема <> "https" Тогда
ЗащищенноеСоединение = Неопределено;
Иначе
Если ЗащищенноеСоединениеКэш = Неопределено Тогда
ЗащищенноеСоединениеКэш = ОбщегоНазначенияКлиентСервер.НовоеЗащищенноеСоединение(
Неопределено,
Новый СертификатыУдостоверяющихЦентровОС);
КонецЕсли;
ЗащищенноеСоединение = ЗащищенноеСоединениеКэш;
КонецЕсли;
Если НЕ ПустаяСтрока(СтруктураURI.Логин) Тогда
ЛогинДляПолучения = СтруктураURI.Логин;
ПарольДляПолучения = СтруктураURI.Пароль;
Иначе
ЛогинДляПолучения = Логин;
ПарольДляПолучения = Пароль;
КонецЕсли;
Если СтруктураURI.Порт = Неопределено ИЛИ ПустаяСтрока(СтруктураURI.Порт) Тогда
Порт = ?(ЗащищенноеСоединение = Неопределено, 80, 443);
Иначе
Порт = Число(СтруктураURI.Порт);
КонецЕсли;
Прокси = ПроксиПоСхемам.Получить(СтруктураURI.Схема);
Если Прокси = Неопределено Тогда
Если ПараметрыПолучения.НастройкиПрокси = Неопределено Тогда
Прокси = ПолучениеФайловИзИнтернета.ПолучитьПрокси(СтруктураURI.Схема);
Иначе
Прокси = СформироватьИнтернетПрокси(ПараметрыПолучения.НастройкиПрокси, СтруктураURI.Схема);
КонецЕсли;
ПроксиПоСхемам.Вставить(СтруктураURI.Схема, Прокси);
КонецЕсли;
Соединение = Новый HTTPСоединение(
СтруктураURI.Хост,
Порт,
ЛогинДляПолучения,
ПарольДляПолучения,
Прокси,
ПараметрыПолучения.Таймаут,
ЗащищенноеСоединение);
Попытка
HTTPЗапрос.АдресРесурса = СтруктураURI.ПутьНаСервере;
Если ПараметрыПолучения.Метод = "GET" Тогда
Ответ = Соединение.Получить(HTTPЗапрос, ПараметрыПолучения.ИмяФайлаОтвета);
ИначеЕсли ПараметрыПолучения.Метод = "HEAD" Тогда
Ответ = Соединение.ПолучитьЗаголовки(HTTPЗапрос);
Иначе
Если НЕ ТелоУстановлено Тогда
Если ПараметрыПолучения.ДанныеДляОбработки <> Неопределено Тогда
Если ПараметрыПолучения.ФорматДанныхДляОбработки = 0 Тогда
HTTPЗапрос.УстановитьИмяФайлаТела(ПараметрыПолучения.ДанныеДляОбработки);
ИначеЕсли ПараметрыПолучения.ФорматДанныхДляОбработки = 1 Тогда
HTTPЗапрос.УстановитьТелоИзСтроки(ПараметрыПолучения.ДанныеДляОбработки);
Иначе
HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ПараметрыПолучения.ДанныеДляОбработки);
КонецЕсли;
КонецЕсли;
ТелоУстановлено = Истина;
КонецЕсли;
Если ПараметрыПолучения.Метод = "PUT" Тогда
Ответ = Соединение.Записать(HTTPЗапрос);
Иначе
// POST
Ответ = Соединение.ОтправитьДляОбработки(HTTPЗапрос, ПараметрыПолучения.ИмяФайлаОтвета);
КонецЕсли;
КонецЕсли;
Исключение
ПредставлениеОшибки = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
ПодробноеОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Не удалось загрузить содержимое (%1). %2'"),
URL,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
// Диагностика соединения с ресурсом.
Попытка
РезультатДиагностики = ПолучениеФайловИзИнтернета.ДиагностикаСоединения(URL);
ОписаниеРезультатаДиагностики = НСтр("ru = 'Результаты диагностики соединения:'")
+ Символы.ПС + РезультатДиагностики.ОписаниеОшибки;
Исключение
ОписаниеРезультатаДиагностики = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Не удалось выполнить диагностику соединения. %1'"),
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
УстановитьОписаниеОшибки(
Результат,
"ConnectError",
ПредставлениеОшибки,
ПодробноеОписаниеОшибки + Символы.ПС + ОписаниеРезультатаДиагностики,
Перенаправления);
Возврат Результат;
КонецПопытки;
Результат.КодСостояния = Ответ.КодСостояния;
Если Ответ.КодСостояния = 301 // 301 Moved Permanently
ИЛИ Ответ.КодСостояния = 302 // 302 Found, 302 Moved Temporarily
ИЛИ Ответ.КодСостояния = 303 // 303 See Other by GET
ИЛИ Ответ.КодСостояния = 307 Тогда // 307 Temporary Redirect
КоличествоПеренаправлений = КоличествоПеренаправлений + 1;
Если КоличествоПеренаправлений > МаксКолвоПеренаправлений Тогда
УстановитьОписаниеОшибки(
Результат,
"ServerError",
НСтр("ru = 'Превышено количество перенаправлений.'"),
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка сервера при получении файла (%1). Превышено количество перенаправлений (%2).'"),
URL,
МаксКолвоПеренаправлений),
Перенаправления);
Возврат Результат;
Иначе
Location = Ответ.Заголовки.Получить("Location");
Если Location = Неопределено Тогда
УстановитьОписаниеОшибки(
Результат,
"ServerError",
НСтр("ru = 'Некорректное перенаправление.'"),
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка сервера (%1) при получении файла (%2). Некорректное перенаправление, отсутствует HTTP-заголовок ответа ""Location"".'"),
Ответ.КодСостояния,
URL),
Перенаправления);
Возврат Результат;
Иначе
Location = СокрЛП(Location);
Если ПустаяСтрока(Location) Тогда
УстановитьОписаниеОшибки(
Результат,
"ServerError",
НСтр("ru = 'Некорректное перенаправление.'"),
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка сервера (%1) при получении файла (%2). Некорректное перенаправление, пустой HTTP-заголовок ответа ""Location"".'"),
Ответ.КодСостояния,
URL),
Перенаправления);
Возврат Результат;
КонецЕсли;
Если ВыполненныеПеренаправления.Получить(Location) <> Неопределено Тогда
УстановитьОписаниеОшибки(
Результат,
"ServerError",
НСтр("ru = 'Циклическое перенаправление.'"),
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка сервера (%1) при получении файла (%2). Циклическое перенаправление (%3).'"),
Ответ.КодСостояния,
URL,
Location),
Перенаправления);
Возврат Результат;
КонецЕсли;
ВыполненныеПеренаправления.Вставить(Location, Истина);
URLДляПолучения = Location;
Перенаправления.Добавить(Строка(Ответ.КодСостояния) + ": " + Location);
КонецЕсли;
КонецЕсли;
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
Если ПараметрыПолучения.ФорматОтвета = 0 Тогда
Результат.Содержимое = Ответ.ПолучитьИмяФайлаТела();
ИначеЕсли ПараметрыПолучения.ФорматОтвета = 1 Тогда
Результат.Содержимое = Ответ.ПолучитьТелоКакСтроку();
ИначеЕсли ПараметрыПолучения.ФорматОтвета = 2 Тогда
Результат.Содержимое = Ответ.ПолучитьТелоКакДвоичныеДанные();
Иначе
Результат.Содержимое = Ответ;
КонецЕсли;
// Обработка ответа
Если Ответ.КодСостояния < 200 Или Ответ.КодСостояния >= 300 Тогда
// Анализ ошибки
Если Ответ.КодСостояния = 407 Тогда
// Ошибка подключения - не пройдена аутентификация на прокси-сервере.
УстановитьОписаниеОшибки(
Результат,
"ConnectError",
НСтр("ru = 'Ошибка аутентификации на прокси-сервере.'"),
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка клиента (%1) при выполнении запроса к ресурсу (%2).
|Тело ответа: %3'"),
Ответ.КодСостояния,
URL,
Лев(Ответ.ПолучитьТелоКакСтроку(), 5120)),
Перенаправления);
ИначеЕсли Ответ.КодСостояния < 200
ИЛИ Ответ.КодСостояния >= 300
И Ответ.КодСостояния < 400 Тогда
// Формат ответа сервера не поддерживается.
УстановитьОписаниеОшибки(
Результат,
"ServerError",
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Некорректный ответ сервера (%1).'"),
Ответ.КодСостояния),
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка сервера при получении файла (%1). Некорректный (неподдерживаемый) ответ (%2).
|Тело ответа: %3'"),
URL,
Ответ.КодСостояния,
Лев(Ответ.ПолучитьТелоКакСтроку(), 5120)),
Перенаправления);
ИначеЕсли Ответ.КодСостояния >= 400 И Ответ.КодСостояния < 500 Тогда
// Ошибка клиентской части - некорректный запрос.
УстановитьОписаниеОшибки(
Результат,
"ClientError",
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка (%1) при выполнении запроса к ресурсу.'"),
Строка(Ответ.КодСостояния)),
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка клиента (%1) при выполнении запроса к ресурсу (%2).
|Тело ответа: %3'"),
Ответ.КодСостояния,
URL,
Лев(Ответ.ПолучитьТелоКакСтроку(), 5120)),
Перенаправления);
Иначе
// Ошибка сервера - 5хх
УстановитьОписаниеОшибки(
Результат,
"ServerError",
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Код ошибки: %1.'"),
Строка(Ответ.КодСостояния)),
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка сервера (%1) при обработке запроса к ресурсу (%2).
|Тело ответа: %3'"),
Ответ.КодСостояния,
URL,
Лев(Ответ.ПолучитьТелоКакСтроку(), 5120)),
Перенаправления);
КонецЕсли;
ДобавитьСписокПеренаправленийКИнформацииОбОшибке(
Результат.ИнформацияОбОшибке,
Перенаправления);
КонецЕсли;
Возврат Результат;
КонецФункции
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////
Загрузить картинку из интернета асинхронно
ОтфильтроватьСодержимоеТекстаHTML (БСП)