diff --git a/src/ru/OPI/src/CommonModules/OPI_S3/Module.bsl b/src/ru/OPI/src/CommonModules/OPI_S3/Module.bsl index 9ec1a80680..b8ad0ecd93 100644 --- a/src/ru/OPI/src/CommonModules/OPI_S3/Module.bsl +++ b/src/ru/OPI/src/CommonModules/OPI_S3/Module.bsl @@ -60,12 +60,14 @@ // Структура Из КлючИЗначение - Структура основных данных запроса Функция ПолучитьСтруктуруДанных(Знач URL, Знач AccessKey, Знач SecretKey, Знач Region, Знач Service = "s3") Экспорт + Строка_ = "Строка"; + СтруктураАвторизации = Новый Структура; - OPI_Инструменты.ДобавитьПоле("URL" , URL , "Строка", СтруктураАвторизации); - OPI_Инструменты.ДобавитьПоле("AccessKey", AccessKey, "Строка", СтруктураАвторизации); - OPI_Инструменты.ДобавитьПоле("SecretKey", SecretKey, "Строка", СтруктураАвторизации); - OPI_Инструменты.ДобавитьПоле("Region" , Region , "Строка", СтруктураАвторизации); - OPI_Инструменты.ДобавитьПоле("Service" , Service , "Строка", СтруктураАвторизации); + OPI_Инструменты.ДобавитьПоле("URL" , URL , Строка_, СтруктураАвторизации); + OPI_Инструменты.ДобавитьПоле("AccessKey", AccessKey, Строка_, СтруктураАвторизации); + OPI_Инструменты.ДобавитьПоле("SecretKey", SecretKey, Строка_, СтруктураАвторизации); + OPI_Инструменты.ДобавитьПоле("Region" , Region , Строка_, СтруктураАвторизации); + OPI_Инструменты.ДобавитьПоле("Service" , Service , Строка_, СтруктураАвторизации); Возврат СтруктураАвторизации; @@ -502,13 +504,15 @@ , Знач ТокенСтраницы = "" , Знач Заголовки = Неопределено) Экспорт + Строка_ = "Строка"; + ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); Параметры = Новый Соответствие; - OPI_Инструменты.ДобавитьПоле("bucket-region" , Регион , "Строка", Параметры); - OPI_Инструменты.ДобавитьПоле("continuation-token", ТокенСтраницы, "Строка", Параметры); - OPI_Инструменты.ДобавитьПоле("max-buckets" , 250 , "Строка", Параметры); - OPI_Инструменты.ДобавитьПоле("prefix" , Префикс , "Строка", Параметры); + OPI_Инструменты.ДобавитьПоле("bucket-region" , Регион , Строка_, Параметры); + OPI_Инструменты.ДобавитьПоле("continuation-token", ТокенСтраницы, Строка_, Параметры); + OPI_Инструменты.ДобавитьПоле("max-buckets" , 250 , Строка_, Параметры); + OPI_Инструменты.ДобавитьПоле("prefix" , Префикс , Строка_, Параметры); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = URL + OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры); @@ -555,7 +559,8 @@ OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Содержимое); РазмерФайла = ПолучитьРазмерСодержимого(Содержимое); - МинимальныйРазмерЧасти = РазмерФайла / 10000; + Делитель = 10000; + МинимальныйРазмерЧасти = РазмерФайла / Делитель; МинимальныйРазмерЧасти = Макс(МинимальныйРазмерЧасти, 5242880); Если OPI_Инструменты.ПолеКоллекцииСуществует(ОсновныеДанные_, "ChunkSize") Тогда @@ -1107,16 +1112,18 @@ , Знач ТокенСтраницы = "" , Знач Заголовки = Неопределено) Экспорт + Строка_ = "Строка"; + ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Бакет, Ложь); Параметры = Новый Соответствие; - OPI_Инструменты.ДобавитьПоле("list-type" , 2 , "Строка", Параметры); - OPI_Инструменты.ДобавитьПоле("max-keys" , 250 , "Строка", Параметры); - OPI_Инструменты.ДобавитьПоле("continuation-token", ТокенСтраницы, "Строка", Параметры); - OPI_Инструменты.ДобавитьПоле("prefix" , Префикс , "Строка", Параметры); + OPI_Инструменты.ДобавитьПоле("list-type" , 2 , Строка_, Параметры); + OPI_Инструменты.ДобавитьПоле("max-keys" , 250 , Строка_, Параметры); + OPI_Инструменты.ДобавитьПоле("continuation-token", ТокенСтраницы, Строка_, Параметры); + OPI_Инструменты.ДобавитьПоле("prefix" , Префикс , Строка_, Параметры); URL = URL + OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры); ОсновныеДанные_.Вставить("URL", URL); @@ -1148,6 +1155,8 @@ , Знач Версия = "" , Знач Заголовки = Неопределено) Экспорт + Строка_ = "Строка"; + ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); URL = ПолучитьURLСервиса(ОсновныеДанные_); @@ -1155,9 +1164,9 @@ URL = URL + "?versions"; Параметры = Новый Соответствие; - OPI_Инструменты.ДобавитьПоле("max-keys" , 250 , "Строка", Параметры); - OPI_Инструменты.ДобавитьПоле("version-id-marker", Версия , "Строка", Параметры); - OPI_Инструменты.ДобавитьПоле("prefix" , Префикс, "Строка", Параметры); + OPI_Инструменты.ДобавитьПоле("max-keys" , 250 , Строка_, Параметры); + OPI_Инструменты.ДобавитьПоле("version-id-marker", Версия , Строка_, Параметры); + OPI_Инструменты.ДобавитьПоле("prefix" , Префикс, Строка_, Параметры); URL = URL + OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры, , Ложь); ОсновныеДанные_.Вставить("URL", URL); @@ -1301,10 +1310,11 @@ ПараметрыСтрокой = OPI_Инструменты.ПараметрыЗапросаВСтроку(ПараметрыURL); ПараметрыСтрокой = Прав(ПараметрыСтрокой, СтрДлина(ПараметрыСтрокой) - 1); ШаблонЗапроса = ""; + ЧислоЧастей = 6; - Для Н = 1 По 6 Цикл + Для Н = 1 По ЧислоЧастей Цикл - ШаблонЗапроса = ШаблонЗапроса + "%" + Строка(Н) + ?(Н = 6, "", Символы.ПС); + ШаблонЗапроса = ШаблонЗапроса + "%" + Строка(Н) + ?(Н = ЧислоЧастей, "", Символы.ПС); КонецЦикла; @@ -1382,12 +1392,13 @@ ШаблонЗапроса = ""; ТелоЗапроса = OPI_Инструменты.ПолучитьТелоЗапроса(Запрос); ХешСумма = OPI_Криптография.Хеш(ТелоЗапроса, ХешФункция.SHA256); + ЧислоЧастей = 6; Запрос.Заголовки.Вставить("x-amz-content-sha256", нРег(ПолучитьHexСтрокуИзДвоичныхДанных(ХешСумма))); - Для Н = 1 По 6 Цикл + Для Н = 1 По ЧислоЧастей Цикл - ШаблонЗапроса = ШаблонЗапроса + "%" + Строка(Н) + ?(Н = 6, "", Символы.ПС); + ШаблонЗапроса = ШаблонЗапроса + "%" + Строка(Н) + ?(Н = ЧислоЧастей, "", Символы.ПС); КонецЦикла; @@ -1432,14 +1443,15 @@ ШаблонСтроки = ""; Алгоритм = "AWS4-HMAC-SHA256"; ДатаISO = OPI_Инструменты.ВременнаяМеткаISO(ТекущаяДата); + ЧислоЧастей = 4; КаноническийЗапрос = ПолучитьДвоичныеДанныеИзСтроки(КаноническийЗапрос); КаноническийЗапрос = OPI_Криптография.Хеш(КаноническийЗапрос, ХешФункция.SHA256); КаноническийЗапрос = нРег(ПолучитьHexСтрокуИзДвоичныхДанных(КаноническийЗапрос)); - Для Н = 1 По 4 Цикл + Для Н = 1 По ЧислоЧастей Цикл - ШаблонСтроки = ШаблонСтроки + "%" + Строка(Н) + ?(Н = 4, "", Символы.ПС); + ШаблонСтроки = ШаблонСтроки + "%" + Строка(Н) + ?(Н = ЧислоЧастей, "", Символы.ПС); КонецЦикла; @@ -1654,10 +1666,11 @@ , Знач ПутьСохранения , Знач Размеры) - ОбщийРазмер = Размеры["object"]; - РазмерУчастка = Размеры["chunk"]; + ОбщийРазмер = Размеры["object"]; + РазмерУчастка = Размеры["chunk"]; ШаблонЗаголовка = "bytes=%1-%2"; - НачалоУчастка = 0; + НачалоУчастка = 0; + Попытки = 3; МассивЗаголовков = Новый Массив; @@ -1684,17 +1697,12 @@ КонецЕсли; - Если ЗначениеЗаполнено(ПутьСохранения) Тогда - ПотокФайла = Новый ФайловыйПоток(ПутьСохранения, РежимОткрытияФайла.Создать); - Иначе - ПотокФайла = Новый ПотокВПамяти(); - КонецЕсли; - + ПотокФайла = OPI_Инструменты.СоздатьПоток(ПутьСохранения); ЗаписьФайла = Новый ЗаписьДанных(ПотокФайла); Для Каждого ТекущийНабор Из МассивЗаголовков Цикл - Для Н = 1 По 3 Цикл + Для Н = 1 По Попытки Цикл Попытка @@ -1719,13 +1727,13 @@ Исключение - Если Н = 3 Тогда + Если Н = Попытки Тогда // !OInt Сообщить(ОписаниеОшибки()); ВызватьИсключение "Не удалось получить файл!"; Иначе - // !OInt Сообщить("Ошибка загрузки участка " + Строка(Н) + "/3"); + // !OInt Сообщить("Ошибка загрузки участка " + Строка(Н) + "/" + Строка(Попытки)); Продолжить; КонецЕсли; @@ -1737,13 +1745,9 @@ ЗаписьФайла.Закрыть(); - Если ТипЗнч(ПотокФайла) = Тип("ПотокВПамяти") Тогда - Возврат ПотокФайла.ЗакрытьИПолучитьДвоичныеДанные(); - Иначе - ПотокФайла.Закрыть(); - ФайлОтвета = Новый Файл(ПутьСохранения); - Возврат ФайлОтвета.ПолноеИмя; - КонецЕсли; + ПолученныйОбъект = ЗакрытьПотокИПолучитьДанные(ПотокФайла, ПутьСохранения); + + Возврат ПолученныйОбъект; КонецФункции @@ -1781,7 +1785,6 @@ ПрочитаноБайт = 0; НомерЧасти = 1; - Если Не OPI_Инструменты.ПолеКоллекцииСуществует(НачалоЗагрузки, ПолеID, IDЗагрузки) Тогда Возврат НачалоЗагрузки; КонецЕсли; @@ -1790,14 +1793,17 @@ ИсходныйПоток = ЧтениеДанных.ИсходныйПоток(); Ответ = Новый Соответствие; МассивТегов = Новый Массив; - Ошибка = Ложь; + + Ошибка = Ложь; + Попытки = 3; + ПоследнийКодУспеха = 299; Пока ПрочитаноБайт < ОбщийРазмер Цикл - Попытка - - Для Н = 1 По 3 Цикл + Для Н = 1 По Попытки Цикл + Попытка + Результат = ЧтениеДанных.Прочитать(РазмерУчастка); ТекущиеДанные = Результат.ПолучитьДвоичныеДанные(); @@ -1812,7 +1818,7 @@ , НомерЧасти , ТекущиеДанные); - Если Ответ["status"] > 299 Тогда + Если Ответ["status"] > ПоследнийКодУспеха Тогда ВызватьИсключение "Сервер вернул статус " + Строка(Ответ["status"]); КонецЕсли; @@ -1832,28 +1838,28 @@ Прервать; - КонецЦикла; + Исключение - Исключение + Если Н = Попытки Тогда - Если Н = 3 Тогда + // !OInt Сообщить(OPI_Инструменты.JSONСтрокой(Ответ)); + // !OInt Сообщить("Не удалось загрузить часть файла! Отмена загрузки ID:" + IDЗагрузки + "..."); - // !OInt Сообщить(OPI_Инструменты.JSONСтрокой(Ответ)); - // !OInt Сообщить("Не удалось загрузить часть файла! Отмена загрузки ID:" + IDЗагрузки + "..."); + Ошибка = Истина; + Прервать; - Ошибка = Истина; - Прервать; + Иначе - Иначе + // !OInt Сообщить("Ошибка загрузки участка " + Строка(Н) + "/" + Строка(Попытки)); + // !OInt Сообщить(ОписаниеОшибки()); + Продолжить; - // !OInt Сообщить("Ошибка загрузки участка " + Строка(Н) + "/3"); - // !OInt Сообщить(ОписаниеОшибки()); - Продолжить; + КонецЕсли; - КонецЕсли; - - КонецПопытки; + КонецПопытки; + КонецЦикла; + НомерЧасти = НомерЧасти + 1; КонецЦикла; @@ -1870,10 +1876,11 @@ Функция ОформитьОтвет(Знач Ответ, Знач ОжидаютсяДвоичные = Ложь) - Статус = Ответ.КодСостояния; - Заголовки = Ответ.Заголовки; + Статус = Ответ.КодСостояния; + Заголовки = Ответ.Заголовки; + ПоследнийКодУспеха = 299; - Если Не ОжидаютсяДвоичные Или Статус > 299 Тогда + Если Не ОжидаютсяДвоичные Или Статус > ПоследнийКодУспеха Тогда ДанныеОтвета = Новый Структура; ДанныеТела = Новый Структура; @@ -1908,13 +1915,15 @@ OPI_ПреобразованиеТипов.ПолучитьСтроку(Имя); OPI_ПреобразованиеТипов.ПолучитьБулево(Каталог); + + Признак = "://"; Если Каталог Тогда URL = URL + Имя; Иначе - Если СтрНайти(URL, "://") Тогда - URL = СтрЗаменить(URL, "://", "://" + Имя + "."); + Если СтрНайти(URL, Признак) Тогда + URL = СтрЗаменить(URL, Признак, Признак + Имя + "."); Иначе URL = Имя + "." + URL; КонецЕсли; @@ -1995,6 +2004,18 @@ КонецФункции +Функция ЗакрытьПотокИПолучитьДанные(Знач ПотокФайла, Знач ПутьСохранения) + + Если ТипЗнч(ПотокФайла) = Тип("ПотокВПамяти") Тогда + Возврат ПотокФайла.ЗакрытьИПолучитьДвоичныеДанные(); + Иначе + ПотокФайла.Закрыть(); + ФайлОтвета = Новый Файл(ПутьСохранения); + Возврат ФайлОтвета.ПолноеИмя; + КонецЕсли; + +КонецФункции + Процедура ПроверитьОсновныеДанные(ОсновныеДанные) ТекстОшибки = "Ошибка получения авторизационных данных из структуры"; diff --git a/src/ru/OPI/src/CommonModules/OPI_Инструменты/Module.bsl b/src/ru/OPI/src/CommonModules/OPI_Инструменты/Module.bsl index c59b26c422..3515471e2a 100644 --- a/src/ru/OPI/src/CommonModules/OPI_Инструменты/Module.bsl +++ b/src/ru/OPI/src/CommonModules/OPI_Инструменты/Module.bsl @@ -191,7 +191,11 @@ КонецФункции -Функция СоздатьСоединение(Знач Сервер, Знач Защищенное = Истина, Знач Пользователь = "", Знач Пароль = "", Знач Порт = "") Экспорт +Функция СоздатьСоединение(Знач Сервер + , Знач Защищенное = Истина + , Знач Пользователь = "" + , Знач Пароль = "" + , Знач Порт = "") Экспорт Если Не ЗначениеЗаполнено(Порт) Тогда Порт = ?(Защищенное, 443, 80); @@ -408,7 +412,10 @@ КонецФункции -Функция JSONСтрокой(Знач Данные, Знач Экранирование = "Нет", Знач ПереносСтрок = Истина, Знач ДвойныеКавычки = Истина) Экспорт +Функция JSONСтрокой(Знач Данные + , Знач Экранирование = "Нет" + , Знач ПереносСтрок = Истина + , Знач ДвойныеКавычки = Истина) Экспорт Перенос = ?(ПереносСтрок, ПереносСтрокJSON.Windows, ПереносСтрокJSON.Нет); @@ -825,6 +832,18 @@ КонецФункции +Функция СоздатьПоток(Знач ПутьКФайлу = Неопределено) Экспорт + + Если ЗначениеЗаполнено(ПутьКФайлу) Тогда + ПотокФайла = Новый ФайловыйПоток(ПутьКФайлу, РежимОткрытияФайла.Создать); + Иначе + ПотокФайла = Новый ПотокВПамяти(); + КонецЕсли; + + Возврат ПотокФайла; + +КонецФункции + Процедура ЗначениеВМассив(Значение) Экспорт Если ТипЗнч(Значение) = Тип("Массив") Тогда diff --git a/src/ru/OPI/src/CommonModules/OPI_ПолучениеДанныхТестов/Module.bsl b/src/ru/OPI/src/CommonModules/OPI_ПолучениеДанныхТестов/Module.bsl index b6665ac47c..a298d7a36f 100644 --- a/src/ru/OPI/src/CommonModules/OPI_ПолучениеДанныхТестов/Module.bsl +++ b/src/ru/OPI/src/CommonModules/OPI_ПолучениеДанныхТестов/Module.bsl @@ -32,6 +32,7 @@ // BSLLS:UsingServiceTag-off // BSLLS:ExecuteExternalCodeInCommonModule-off // BSLLS:DuplicateStringLiteral-off +// BSLLS:MagicNumber-off //@skip-check use-non-recommended-method //@skip-check module-structure-top-region @@ -2046,6 +2047,7 @@ Возврат Модуль; КонецФункции +// BSLLS:CognitiveComplexity-off Функция ПолучитьЗначениеДляCLI(Знач Значение, Знач Вложенный = Ложь) ТекущийТип = ТипЗнч(Значение); @@ -2081,8 +2083,12 @@ Иначе + // BSLLS:MissingTemporaryFileDeletion-off + //@skip-check missing-temporary-file-deletion ИВТ = ПолучитьИмяВременногоФайла("json"); + // BSLLS:MissingTemporaryFileDeletion-on + Поток = Новый ФайловыйПоток(ИВТ, РежимОткрытияФайла.Создать); ЗаписьJSON.ОткрытьПоток(Поток); @@ -2118,6 +2124,7 @@ Возврат Значение; КонецФункции +// BSLLS:CognitiveComplexity-on Функция ОформитьОпцию(Знач Значение, Знач Имя, Знач Вложенный = Ложь)