// OneScript: ./OInt/core/Modules/OPI_S3.os // Lib: S3 // CLI: s3 // Keywords: s3, minio, aws, simple storage service // MIT License // Copyright (c) 2023-2025 Anton Tsitavets // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // https://github.com/Bayselonarrend/OpenIntegrations // BSLLS:Typo-off // BSLLS:LatinAndCyrillicSymbolInWord-off // BSLLS:IncorrectLineBreak-off // BSLLS:NumberOfOptionalParams-off // BSLLS:UsingServiceTag-off // BSLLS:LineLength-off // BSLLS:UsingSynchronousCalls-off // BSLLS:MagicNumber-off //@skip-check module-structure-top-region //@skip-check module-structure-method-in-regions //@skip-check wrong-string-literal-content //@skip-check method-too-many-params //@skip-check constructor-function-return-section //@skip-check bsl-legacy-check-expression-type #Область ПрограммныйИнтерфейс #Область ОбщиеМетоды // Получить структуру данных // Возвращает основные данные запроса в структурированном виде // // Параметры: // URL - Строка - URL: домен для обычных методов или полный URL с параметрами для прямой отправки запросов - url // AccessKey - Строка - Access key для авторизации - access // SecretKey - Строка - Secret key для авторизации - secret // Region - Строка - Регион сервиса - region // Service - Строка - Вид сервиса, если отличен от s3 - service // // Возвращаемое значение: // Структура Из КлючИЗначение - Структура основных данных запроса Функция ПолучитьСтруктуруДанных(Знач URL, Знач AccessKey, Знач SecretKey, Знач Region, Знач Service = "s3") Экспорт Строка_ = "Строка"; СтруктураАвторизации = Новый Структура; OPI_Инструменты.ДобавитьПоле("URL" , URL , Строка_, СтруктураАвторизации); OPI_Инструменты.ДобавитьПоле("AccessKey", AccessKey, Строка_, СтруктураАвторизации); OPI_Инструменты.ДобавитьПоле("SecretKey", SecretKey, Строка_, СтруктураАвторизации); OPI_Инструменты.ДобавитьПоле("Region" , Region , Строка_, СтруктураАвторизации); OPI_Инструменты.ДобавитьПоле("Service" , Service , Строка_, СтруктураАвторизации); Возврат СтруктураАвторизации; КонецФункции // Отправить запрос без тела // Отправляет простой http запрос без тела // // Параметры: // Метод - Строка - HTTP метод - method // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса (c полным URL). См. ПолучитьСтруктуруДанных - basic // ОжидаютсяДвоичные - Булево - Отключает попытку преобразования ответа в JSON - binary // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ОтправитьЗапросБезТела(Знач Метод , Знач ОсновныеДанные , Знач ОжидаютсяДвоичные = Ложь , Знач Заголовки = Неопределено) Экспорт Ответ = ОтправитьЗапрос(Метод, ОсновныеДанные, , ОжидаютсяДвоичные, Заголовки); Возврат Ответ; КонецФункции // Отправить запрос с телом // Отправляет http запрос с телом // // Параметры: // Метод - Строка - HTTP метод - method // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса (c полным URL). См. ПолучитьСтруктуруДанных - basic // Тело - Строка, ДвоичныеДанные - Двоичное тело запроса или путь к файлу - body // ОжидаютсяДвоичные - Булево - Отключает попытку преобразования ответа в JSON - binary // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ОтправитьЗапросСТелом(Знач Метод , Знач ОсновныеДанные , Знач Тело , Знач ОжидаютсяДвоичные = Ложь , Знач Заголовки = Неопределено) Экспорт Ответ = ОтправитьЗапрос(Метод, ОсновныеДанные, Тело, ОжидаютсяДвоичные, Заголовки); Возврат Ответ; КонецФункции #КонецОбласти #Область РаботаСБакетами // Создать бакет // Создает новый бакет с выбранным именем // // Примечание: // Метод в документации AWS: [CreateBucket](@docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html) // // Параметры: // Наименование - Строка - Наименование бакета - name // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция СоздатьБакет(Знач Наименование, Знач ОсновныеДанные, Знач Каталог = Ложь, Знач Заголовки = Неопределено) Экспорт Ответ = УправлениеБакетом(Наименование, ОсновныеДанные, Каталог, "PUT", Заголовки); Возврат Ответ; КонецФункции // Удалить бакет // Удаляет бакет с выбранным именем // // Примечание: // Метод в документации AWS: [DeleteBucket](@docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html) // // Параметры: // Наименование - Строка - Наименование бакета - name // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция УдалитьБакет(Знач Наименование, Знач ОсновныеДанные, Знач Каталог = Ложь, Знач Заголовки = Неопределено) Экспорт Ответ = УправлениеБакетом(Наименование, ОсновныеДанные, Каталог, "DELETE", Заголовки); Возврат Ответ; КонецФункции // Проверить доступность бакета // Проверяет доступность бакета для текущего аккаунта или аккаунта по ID // // Примечание: // Метод в документации AWS: [HeadBucket](@docs.aws.amazon.com/AmazonS3/latest/API/API_HeadBucket.html) // // Параметры: // Наименование - Строка - Наименование бакета - name // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // IDАккаунта - Строка - ID аккаунта для проверки, что бакет принадлежит ему - account // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ПроверитьДоступностьБакета(Знач Наименование , Знач ОсновныеДанные , Знач Каталог = Ложь , Знач IDАккаунта = "" , Знач Заголовки = Неопределено) Экспорт OPI_ПреобразованиеТипов.ПолучитьСтроку(IDАккаунта); Если ЗначениеЗаполнено(IDАккаунта) Тогда ЗаголовокАккаунта = Новый Соответствие(); ЗаголовокАккаунта.Вставить("x-amz-expected-bucket-owner", IDАккаунта); ДобавитьДополнительныеЗаголовки(Заголовки, ЗаголовокАккаунта); КонецЕсли; Ответ = УправлениеБакетом(Наименование, ОсновныеДанные, Каталог, "HEAD", Заголовки); Возврат Ответ; КонецФункции // Установить шифрование бакета // Устанавлиает шифрование бакета по XML конфигурации // // Примечание: // Метод в документации AWS: [PutBucketEncryption](@docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) // // Параметры: // Наименование - Строка - Наименование бакета - name // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // XMLКонфигурация - Строка - XML строка или файл конфигурации шифрования - conf // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция УстановитьШифрованиеБакета(Знач Наименование , Знач ОсновныеДанные , Знач XMLКонфигурация , Знач Каталог = Ложь , Знач Заголовки = Неопределено) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); OPI_ПреобразованиеТипов.ПолучитьСтроку(XMLКонфигурация, Истина); XMLКонфигурация = ПолучитьДвоичныеДанныеИзСтроки(XMLКонфигурация); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Наименование, Каталог); URL = URL + "?encryption"; ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросСТелом("PUT", ОсновныеДанные_, XMLКонфигурация, , Заголовки); Возврат Ответ; КонецФункции // Получить шифрование бакета // Получает установленную ранее конфигурацию шифрования бакета // // Примечание: // Метод в документации AWS: [GetBucketEncryption](@docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html) // // Параметры: // Наименование - Строка - Наименование бакета - name // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ПолучитьШифрованиеБакета(Знач Наименование , Знач ОсновныеДанные , Знач Каталог = Ложь , Знач Заголовки = Неопределено) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Наименование, Каталог); URL = URL + "?encryption"; ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросБезТела("GET", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции // Удалить шифрование бакета // Удаляет конфигурацию шифрования бакета // // Примечание: // Метод в документации AWS: [DeleteBucketEncryption](@docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketEncryption.html) // // Параметры: // Наименование - Строка - Наименование бакета - name // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция УдалитьШифрованиеБакета(Знач Наименование , Знач ОсновныеДанные , Знач Каталог = Ложь , Знач Заголовки = Неопределено) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Наименование, Каталог); URL = URL + "?encryption"; ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросБезТела("DELETE", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции // Установить теги бакета // Устанавливает набор тегов для бакета // // Примечание: // Установка нового набора удаляет все существующие теги бакета // Метод в документации AWS: [PutBucketTagging](@docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketTagging.html) // // Параметры: // Наименование - Строка - Наименование бакета - name // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Теги - Структура Из КлючИЗначение - Набор тегов (ключ и значение) для установки - tagset // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция УстановитьТегиБакета(Знач Наименование , Знач ОсновныеДанные , Знач Теги , Знач Каталог = Ложь , Знач Заголовки = Неопределено) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); Теги = СформироватьСтруктуруТегов(Теги); ТегиXML = OPI_Инструменты.ПолучитьXML(Теги, "http://s3.amazonaws.com/doc/2006-03-01/"); ТегиXML = ПолучитьДвоичныеДанныеИзСтроки(ТегиXML); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Наименование, Каталог); URL = URL + "?tagging"; ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросСТелом("PUT", ОсновныеДанные_, ТегиXML, , Заголовки); Возврат Ответ; КонецФункции // Получить теги бакета // Получает набор тегов бакета // // Примечание: // Метод в документации AWS: [GetBucketTagging](@docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketTagging.html) // // Параметры: // Наименование - Строка - Наименование бакета - name // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ПолучитьТегиБакета(Знач Наименование , Знач ОсновныеДанные , Знач Каталог = Ложь , Знач Заголовки = Неопределено) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Наименование, Каталог); URL = URL + "?tagging"; ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросБезТела("GET", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции // Удалить теги бакета // Удаляет набор тегов бакета // // Примечание: // Метод в документации AWS: [DeleteBucketTagging](@docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketTagging.html) // // Параметры: // Наименование - Строка - Наименование бакета - name // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция УдалитьТегиБакета(Знач Наименование , Знач ОсновныеДанные , Знач Каталог = Ложь , Знач Заголовки = Неопределено) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Наименование, Каталог); URL = URL + "?tagging"; ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросБезТела("DELETE", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции // Установить настройки версионирования бакета // Устанавливает настройки версионирования объектов бакета // // Примечание: // Метод в документации AWS: [PutBucketVersioning](@docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketVersioning.html) // // Параметры: // Наименование - Строка - Наименование бакета - name // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Статус - Булево - Включение и отключение версионирования, если необходимо - status // УдалениеMFA - Булево - Включение и отключение удаления MFA, если необходимо - mfad // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция УстановитьНастройкиВерсионированияБакета(Знач Наименование , Знач ОсновныеДанные , Знач Статус = Неопределено , Знач УдалениеMFA = Неопределено , Знач Каталог = Ложь , Знач Заголовки = Неопределено) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); Теги = СформироватьСтруктуруНастроекВерсионирования(Статус, УдалениеMFA); ТегиXML = OPI_Инструменты.ПолучитьXML(Теги, "http://s3.amazonaws.com/doc/2006-03-01/"); ТегиXML = ПолучитьДвоичныеДанныеИзСтроки(ТегиXML); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Наименование, Каталог); URL = URL + "?versioning"; ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросСТелом("PUT", ОсновныеДанные_, ТегиXML, , Заголовки); Возврат Ответ; КонецФункции // Получить настройки версионирования бакета // Получает значения настроек версионирования объектов в бакете // // Примечание: // Метод в документации AWS: [GetBucketVersioning](@docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketVersioning.html) // // Параметры: // Наименование - Строка - Наименование бакета - name // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ПолучитьНастройкийВерсионированияБакета(Знач Наименование , Знач ОсновныеДанные , Знач Каталог = Ложь , Знач Заголовки = Неопределено) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Наименование, Каталог); URL = URL + "?versioning"; ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросБезТела("GET", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции // Получить список бакетов // Получает список бакетов. Возможно использование отборов, если они поддерживаются сервисом // // Примечание: // Метод в документации AWS: [ListBuckets](@docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html) // // Параметры: // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Префикс - Строка - Отбор по префиксу, если необходимо - prefix // Регион - Строка - Отбор по региону бакета, если необходимо - region // ТокенСтраницы - Строка - Токен страницы, если используется пагинация - ctoken // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ПолучитьСписокБакетов(Знач ОсновныеДанные , Знач Префикс = "" , Знач Регион = "" , Знач ТокенСтраницы = "" , Знач Заголовки = Неопределено) Экспорт Строка_ = "Строка"; ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); Параметры = Новый Соответствие; OPI_Инструменты.ДобавитьПоле("bucket-region" , Регион , Строка_, Параметры); OPI_Инструменты.ДобавитьПоле("continuation-token", ТокенСтраницы, Строка_, Параметры); OPI_Инструменты.ДобавитьПоле("max-buckets" , 250 , Строка_, Параметры); OPI_Инструменты.ДобавитьПоле("prefix" , Префикс , Строка_, Параметры); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = URL + OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры); ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросБезТела("GET", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции #КонецОбласти #Область РаботаСОбъектами // Загрузить объект // Загружает файл в бакет // // Примечание: // Метод в документации AWS (стандартный): [PutObject](@docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)^ // Метод в документации AWS (по частям): [Multipart upload](@docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html) // Вы можете использовать поле `ChunkSize` в основных данных для указания минимального размера и величины чанка загрузки по частям.^^ // Например, `ChunkSize равный X` означает, что все файлы, размером больше `X` (в байтах) будут загружаться по частям, где одна часть будет размером `X`.^^ // Загрузка по частям используется для больших файлов. Стандартный размер `ChunkSize` - 20971520 байт (20 МБайт) // // Параметры: // Наименование - Строка - Наименование объекта в бакете - name // Бакет - Строка - Имя бакета для загрузки объекта - bucket // Содержимое - Строка, ДвоичныеДанные - Данные или путь к файлу для загрузки - data // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ЗагрузитьОбъект(Знач Наименование , Знач Бакет , Знач Содержимое , Знач ОсновныеДанные , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Содержимое); РазмерФайла = ПолучитьРазмерСодержимого(Содержимое); Делитель = 10000; МинимальныйРазмерЧасти = РазмерФайла / Делитель; МинимальныйРазмерЧасти = Макс(МинимальныйРазмерЧасти, 5242880); Половина = 0.5; Если OPI_Инструменты.ПолеКоллекцииСуществует(ОсновныеДанные_, "ChunkSize") Тогда МаксимальныйРазмер = ОсновныеДанные_["ChunkSize"]; OPI_ПреобразованиеТипов.ПолучитьЧисло(МаксимальныйРазмер); Иначе МаксимальныйРазмер = 20971520; КонецЕсли; Если МинимальныйРазмерЧасти > МаксимальныйРазмер Тогда ВызватьИсключение "ChunkSize слишком мал. Необходимо увеличить размер части (минимум для данного файла - " + OPI_Инструменты.ЧислоВСтроку(Окр(МинимальныйРазмерЧасти + Половина)) + ")"; КонецЕсли; Если РазмерФайла > МаксимальныйРазмер Тогда Размеры = Новый Структура("object,chunk", РазмерФайла, МаксимальныйРазмер); Ответ = ЗагрузитьОбъектЧастями(Наименование, Бакет, Содержимое, ОсновныеДанные_, Заголовки, Размеры, Каталог); Иначе Ответ = ЗагрузитьОбъектЦеликом(Наименование, Бакет, Содержимое, ОсновныеДанные_, Заголовки, Каталог); КонецЕсли; Возврат Ответ; КонецФункции // Загрузить объект целиком // Загружает объект на сервер не используюя загрузку по частям // // Примечание: // Метод в документации AWS: [PutObject](@docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) // Это служебный метод. Для простого сценария загрузки файлов предназначен единый метод `ЗагрузитьОбъект`^ // Использование данного метода для больших файлов может приводить к сбоям // // Параметры: // Наименование - Строка - Наименование объекта в бакете - name // Бакет - Строка - Имя бакета для загрузки объекта - bucket // Содержимое - Строка, ДвоичныеДанные - Данные или путь к файлу для загрузки - data // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ЗагрузитьОбъектЦеликом(Знач Наименование , Знач Бакет , Знач Содержимое , Знач ОсновныеДанные , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); ЗаполнитьURLОбъекта(ОсновныеДанные_, Наименование, Бакет, , Каталог); Ответ = ОтправитьЗапрос("PUT", ОсновныеДанные_, Содержимое, , Заголовки); Возврат Ответ; КонецФункции // Инициализировать загрузку частями // Инициализирует загрузку объекта по частям // // Примечание: // Метод в документации AWS: [CreateMultipartUpload](@docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html) // Это служебный метод. Для простого сценария загрузки файлов предназначен единый метод `ЗагрузитьОбъект`^ // Использование загрузки частями для файлов < 5 МБ или при размере одной части < 5 МБ приведет к ошибке // // Параметры: // Наименование - Строка - Наименование объекта в бакете - name // Бакет - Строка - Имя бакета для загрузки объекта - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ИнициализироватьЗагрузкуЧастями(Знач Наименование , Знач Бакет , Знач ОсновныеДанные , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); ЗаполнитьURLОбъекта(ОсновныеДанные_, Наименование, Бакет, , Каталог); ОсновныеДанные_.Вставить("URL", ОсновныеДанные_["URL"] + "?uploads"); Ответ = ОтправитьЗапросБезТела("POST", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции // Загрузить часть объекта // Загружает часть объекта при загрузке по частям // // Примечание: // Метод в документации AWS: [UploadPart](@docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html) // Это служебный метод. Для простого сценария загрузки файлов предназначен единый метод `ЗагрузитьОбъект` // // Параметры: // Наименование - Строка - Наименование объекта в бакете - name // Бакет - Строка - Имя бакета для загрузки объекта - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // IDЗагрузки - Строка - ID загрузки по частям. См. ИнициализироватьЗагрузкуЧастями - upload // НомерЧасти - Число, Строка - Порядковый номер части объекта от 1 до 10000 - part // Данные - ДвоичныеДанные, Строка - Данные части для загрузки - content // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ЗагрузитьЧастьОбъекта(Знач Наименование , Знач Бакет , Знач ОсновныеДанные , Знач IDЗагрузки , Знач НомерЧасти , Знач Данные , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); ЗаполнитьURLОбъекта(ОсновныеДанные_, Наименование, Бакет, , Каталог); Параметры = Новый Структура; OPI_Инструменты.ДобавитьПоле("partNumber", НомерЧасти, "Строка", Параметры); OPI_Инструменты.ДобавитьПоле("uploadId" , IDЗагрузки, "Строка", Параметры); СтрокаПараметров = OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры); ОсновныеДанные_.Вставить("URL", ОсновныеДанные_["URL"] + СтрокаПараметров); Ответ = ОтправитьЗапросСТелом("PUT", ОсновныеДанные_, Данные); Возврат Ответ; КонецФункции // Завершить загрузку частями // Подтверждает окончание загрузки объекта по частям // // Примечание: // Метод в документации AWS: [CompleteMultipartUpload](@docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html) // Это служебный метод. Для простого сценария загрузки файлов предназначен единый метод `ЗагрузитьОбъект` // // Параметры: // Наименование - Строка - Наименование объекта в бакете - name // Бакет - Строка - Имя бакета для загрузки объекта - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // IDЗагрузки - Строка - ID загрузки по частям. См. ИнициализироватьЗагрузкуЧастями - upload // МассивТегов - Массив Из Строка - Массив тегов (Etag) из загрузок каждой части - tags // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ЗавершитьЗагрузкуЧастями(Знач Наименование , Знач Бакет , Знач ОсновныеДанные , Знач IDЗагрузки , Знач МассивТегов , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); OPI_ПреобразованиеТипов.ПолучитьМассив(МассивТегов); ЗаполнитьURLОбъекта(ОсновныеДанные_, Наименование, Бакет, , Каталог); ОсновныеДанные_.Вставить("URL", ОсновныеДанные_["URL"] + "?uploadId=" + Строка(IDЗагрузки)); МассивЧастей = Новый Массив; Для Н = 1 По МассивТегов.Количество() Цикл СтруктураЧасти = Новый Структура; СтруктураЧасти.Вставить("ETag" , МассивТегов[Н - 1]); СтруктураЧасти.Вставить("PartNumber", Н); МассивЧастей.Добавить(Новый Структура("Part", СтруктураЧасти)); КонецЦикла; СтруктураЗавершения = Новый Структура("CompleteMultipartUpload", МассивЧастей); XMLЗавершения = OPI_Инструменты.ПолучитьXML(СтруктураЗавершения, "http://s3.amazonaws.com/doc/2006-03-01/"); XMLЗавершения = ПолучитьДвоичныеДанныеИзСтроки(XMLЗавершения); Ответ = ОтправитьЗапросСТелом("POST", ОсновныеДанные_, XMLЗавершения, , Заголовки); Возврат Ответ; КонецФункции // Отменить загрузку частями // Отменяет загрузку объекта по частям // // Примечание: // Метод в документации AWS: [AbortMultipartUpload](@docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html) // Это служебный метод. Для простого сценария загрузки файлов предназначен единый метод `ЗагрузитьОбъект`^ // // Параметры: // Наименование - Строка - Наименование объекта в бакете - name // Бакет - Строка - Имя бакета для загрузки объекта - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // IDЗагрузки - Строка - ID загрузки по частям. См. ИнициализироватьЗагрузкуЧастями - upload // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ОтменитьЗагрузкуЧастями(Знач Наименование , Знач Бакет , Знач ОсновныеДанные , Знач IDЗагрузки , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); ЗаполнитьURLОбъекта(ОсновныеДанные_, Наименование, Бакет, , Каталог); ОсновныеДанные_.Вставить("URL", ОсновныеДанные_["URL"] + "?uploadId=" + Строка(IDЗагрузки)); Ответ = ОтправитьЗапросБезТела("DELETE", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции // Получить описание объекта // Получает информацию о характеристиках объекта в бакете // // Примечание: // Метаданные объекты содержатся в заголовках // Метод в документации AWS: [GetObjectAttributes](@docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAttributes.html) // // Параметры: // Наименование - Строка - Наименование объекта в бакете - name // Бакет - Строка - Имя бакета, в котором находится объект - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Версия - Строка - Токен для получения конкретной версии объекта - ver // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ПолучитьОписаниеОбъекта(Знач Наименование , Знач Бакет , Знач ОсновныеДанные , Знач Версия = Неопределено , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); ЗаполнитьURLОбъекта(ОсновныеДанные_, Наименование, Бакет, Версия, Каталог); Ответ = ОтправитьЗапросБезТела("HEAD", ОсновныеДанные_, , Заголовки); Ответ["response"] = Новый Структура; Возврат Ответ; КонецФункции // Получить объект // Получает содержимое объекта из бакета // // Примечание: // Метод в документации AWS: [GetObjectAttributes](@docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAttributes.html) // Вы можете использовать поле `ChunkSize` в основных данных для указания минимального размера и величины чанка загрузки по частям.^^ // Например, `ChunkSize равный X` означает, что все файлы, размером больше `X` (в байтах) будут загружаться по частям, где одна часть будет размером `X`.^^ // Загрузка по частям используется для больших файлов. Стандартный размер `ChunkSize` - 20971520 байт (20 МБайт) // // Параметры: // Наименование - Строка - Наименование объекта в бакете - name // Бакет - Строка - Имя бакета, в котором находится объект - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Версия - Строка - Токен для получения конкретной версии объекта - ver // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // ПутьСохранения - Строка - Путь для прямой записи файла на диск - out // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // ДвоичныеДанные, Строка - содержимое объекта или путь к файлу, если указан путь сохранения Функция ПолучитьОбъект(Знач Наименование , Знач Бакет , Знач ОсновныеДанные , Знач Версия = "" , Знач Заголовки = Неопределено , Знач ПутьСохранения = "" , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); ИнформацияОбъекта = ПолучитьОписаниеОбъекта(Наименование, Бакет, ОсновныеДанные_, Версия); Если OPI_Инструменты.ПолеКоллекцииСуществует(ОсновныеДанные_, "ChunkSize") Тогда МаксимальныйРазмер = ОсновныеДанные_["ChunkSize"]; OPI_ПреобразованиеТипов.ПолучитьЧисло(МаксимальныйРазмер); Иначе МаксимальныйРазмер = 20971520; КонецЕсли; Если Не OPI_Инструменты.ПолеКоллекцииСуществует(ИнформацияОбъекта, "headers.Content-Length") Тогда Возврат ИнформацияОбъекта; КонецЕсли; РазмерОбъекта = ИнформацияОбъекта["headers"]["Content-Length"]; ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); OPI_ПреобразованиеТипов.ПолучитьЧисло(МаксимальныйРазмер); OPI_ПреобразованиеТипов.ПолучитьЧисло(РазмерОбъекта); ЗаполнитьURLОбъекта(ОсновныеДанные_, Наименование, Бакет, Версия, Каталог); Если РазмерОбъекта > МаксимальныйРазмер Тогда Размеры = Новый Структура("object,chunk", РазмерОбъекта, МаксимальныйРазмер); Ответ = ПолучитьОбъектЧастями(ОсновныеДанные_, Заголовки, ПутьСохранения, Размеры); Иначе Ответ = ПолучитьОбъектЦеликом(ОсновныеДанные_, Заголовки, ПутьСохранения); КонецЕсли; Возврат Ответ; КонецФункции // Удалить объект // Удаляет объект из бакета // // Примечание: // Метод в документации AWS: [DeleteObject](@docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html) // // Параметры: // Наименование - Строка - Наименование объекта в бакете - name // Бакет - Строка - Имя бакета для загрузки объекта - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Версия - Строка - Токен для удаления конкретной версии объекта - ver // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция УдалитьОбъект(Знач Наименование , Знач Бакет , Знач ОсновныеДанные , Знач Версия = Неопределено , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Бакет, Каталог); URL = URL + Наименование; Если ЗначениеЗаполнено(Версия) Тогда OPI_ПреобразованиеТипов.ПолучитьСтроку(Версия); URL = URL + "?versionId=" + Версия; КонецЕсли; ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросБезТела("DELETE", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции // Копировать объект // Копирует объект из одного расположения в другое // // Примечание: // Метод в документации AWS: [CopyObject](@docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html) // // Параметры: // ПутьИсточник - Строка - Путь (имя) в бакете источнике - sname // БакетИсточник - Строка - Бакет источник объекта - sbucket // ПутьПриемник - Строка - Путь (имя) объекта в бакете приемнике - name // БакетПриемник - Строка - Имя бакета приемника - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция КопироватьОбъект(Знач ПутьИсточник , Знач БакетИсточник , Знач ПутьПриемник , Знач БакетПриемник , Знач ОсновныеДанные , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); OPI_ПреобразованиеТипов.ПолучитьСтроку(ПутьИсточник); OPI_ПреобразованиеТипов.ПолучитьСтроку(БакетИсточник); Источник = БакетИсточник + "/" + ПутьИсточник; Источник = ?(СтрНачинаетсяС(Источник, "/"), Источник, "/" + Источник); ЗаголовокИсточника = Новый Соответствие(); ЗаголовокИсточника.Вставить("x-amz-copy-source", Источник); ДобавитьДополнительныеЗаголовки(Заголовки, ЗаголовокИсточника); Ответ = ЗагрузитьОбъектЦеликом(ПутьПриемник, БакетПриемник, Неопределено, ОсновныеДанные_, Заголовки, Каталог); Возврат Ответ; КонецФункции // Установить теги объекта // Устанавливает набор тегов для объекта // // Примечание: // Установка нового набора удаляет все существующие теги объекта // Метод в документации AWS: [PutObjectTagging](@docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html) // // Параметры: // Наименование - Строка - Наименование объекта - name // Бакет - Строка - Наименование бакета - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Теги - Структура Из КлючИЗначение - Набор тегов (ключ и значение) для установки - tagset // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция УстановитьТегиОбъекта(Знач Наименование , Знач Бакет , Знач ОсновныеДанные , Знач Теги , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование); Теги = СформироватьСтруктуруТегов(Теги); ТегиXML = OPI_Инструменты.ПолучитьXML(Теги, "http://s3.amazonaws.com/doc/2006-03-01/"); ТегиXML = ПолучитьДвоичныеДанныеИзСтроки(ТегиXML); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Бакет, Каталог); URL = URL + Наименование + "?tagging"; ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросСТелом("PUT", ОсновныеДанные_, ТегиXML, , Заголовки); Возврат Ответ; КонецФункции // Получить теги объекта // Получает набор тегов объекта // // Примечание: // Метод в документации AWS: [GetObjectTagging](@docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html) // // Параметры: // Наименование - Строка - Наименование объекта - name // Бакет - Строка - Наименование бакета - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Версия - Строка - Токен для получения данных конкретной версии объекта - ver // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ПолучитьТегиОбъекта(Знач Наименование , Знач Бакет , Знач ОсновныеДанные , Знач Версия = "" , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование); OPI_ПреобразованиеТипов.ПолучитьСтроку(Версия); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Бакет, Каталог); URL = URL + Наименование + "?tagging"; Если ЗначениеЗаполнено(Версия) Тогда URL = URL + "&versionId=" + Версия; КонецЕсли; ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросБезТела("GET", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции // Удалить теги объекта // Удаляет набор тегов объекта // // Примечание: // Метод в документации AWS: [DeleteObjectTagging](@docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjectTagging.html) // // Параметры: // Наименование - Строка - Наименование объекта - name // Бакет - Строка - Наименование бакета - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Версия - Строка - Токен для удаления данных конкретной версии объекта - ver // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция УдалитьТегиОбъекта(Знач Наименование , Знач Бакет , Знач ОсновныеДанные , Знач Версия = "" , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование); OPI_ПреобразованиеТипов.ПолучитьСтроку(Версия); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Бакет, Каталог); URL = URL + Наименование + "?tagging"; Если ЗначениеЗаполнено(Версия) Тогда URL = URL + "&versionId=" + Версия; КонецЕсли; ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросБезТела("DELETE", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции // Получить список объектов // Получает список объектов в выбранном бакете // // Примечание: // Метод в документации AWS: [ListObjectsV2](@docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html) // // Параметры: // Бакет - Строка - Наименование бакета - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Префикс - Строка - Отбор по префиксу, если необходимо - prefix // ТокенСтраницы - Строка - Токен страницы, если используется пагинация - ctoken // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ПолучитьСписокОбъектов(Знач Бакет , Знач ОсновныеДанные , Знач Префикс = "" , Знач ТокенСтраницы = "" , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт Строка_ = "Строка"; ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Бакет, Каталог); Параметры = Новый Соответствие; OPI_Инструменты.ДобавитьПоле("list-type" , 2 , Строка_, Параметры); OPI_Инструменты.ДобавитьПоле("max-keys" , 250 , Строка_, Параметры); OPI_Инструменты.ДобавитьПоле("continuation-token", ТокенСтраницы, Строка_, Параметры); OPI_Инструменты.ДобавитьПоле("prefix" , Префикс , Строка_, Параметры); URL = URL + OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры); ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросБезТела("GET", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции // Получить список версий объектов // Получает список всех версий объектов в выбранном бакете // // Примечание: // Метод в документации AWS: [ListObjectVersions](@docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html) // // Параметры: // Бакет - Строка - Наименование бакета - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // Префикс - Строка - Отбор по префиксу, если необходимо - prefix // Версия - Строка - ID версии начала списка - ver // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Структура Из КлючИЗначение - сериализованный JSON ответа от хранилища Функция ПолучитьСписокВерсийОбъектов(Знач Бакет , Знач ОсновныеДанные , Знач Префикс = "" , Знач Версия = "" , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт Строка_ = "Строка"; ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Бакет, Каталог); URL = URL + "?versions"; Параметры = Новый Соответствие; OPI_Инструменты.ДобавитьПоле("max-keys" , 250 , Строка_, Параметры); OPI_Инструменты.ДобавитьПоле("version-id-marker", Версия , Строка_, Параметры); OPI_Инструменты.ДобавитьПоле("prefix" , Префикс, Строка_, Параметры); URL = URL + OPI_Инструменты.ПараметрыЗапросаВСтроку(Параметры, , Ложь); ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросБезТела("GET", ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции // Получить ссылку скачивания объекта // Получает прямую ссылку для скачивания объекта без дополнительной авторизации // // Примечание: // В Заголовки необходимо добавить все x-amz заголовки, которые будут использоваться при обращении к полученному URL // О механизме в документации AWS: [Download and upload objects with presigned URLs](@docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html) // // Параметры: // Наименование - Строка - Наименование объекта в бакете - name // Бакет - Строка - Имя бакета для загрузки объекта - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // ВремяЖизни - Строка, Число - Время жизни ссылки в секундах. 604800 максимум - expires // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Строка - URL для получения объекта Функция ПолучитьСсылкуСкачиванияОбъекта(Знач Наименование , Знач Бакет , Знач ОсновныеДанные , Знач ВремяЖизни = 3600 , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); ПроверитьОсновныеДанные(ОсновныеДанные_); ЗаполнитьURLОбъекта(ОсновныеДанные_, Наименование, Бакет, , Каталог); Подпись = СоздатьПодписьURL(ОсновныеДанные_, "GET", ВремяЖизни, Заголовки); URL = ОсновныеДанные_["URL"] + Подпись; Возврат URL; КонецФункции // Получить ссылку загрузки объекта // Получает прямую ссылку для загрузки объекта без дополнительной авторизации // // Примечание: // В Заголовки необходимо добавить все x-amz заголовки, которые будут использоваться при обращении к полученному URL // О механизме в документации AWS: [Download and upload objects with presigned URLs](@docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html) // // Параметры: // Наименование - Строка - Наименование объекта в бакете - name // Бакет - Строка - Имя бакета для загрузки объекта - bucket // ОсновныеДанные - Структура Из КлючИЗначение - Основные данные запроса. См. ПолучитьСтруктуруДанных - basic // ВремяЖизни - Строка, Число - Время жизни ссылки в секундах. 604800 максимум - expires // Заголовки - Соответствие Из КлючИЗначение - Дополнительные заголовки запроса, если необходимо - headers // Каталог - Булево - Истина > Path style URL, Ложь > Virtual hosted style URL - dir // // Возвращаемое значение: // Строка - URL для получения объекта Функция ПолучитьСсылкуЗагрузкиОбъекта(Знач Наименование , Знач Бакет , Знач ОсновныеДанные , Знач ВремяЖизни = 3600 , Знач Заголовки = Неопределено , Знач Каталог = Ложь) Экспорт ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); ПроверитьОсновныеДанные(ОсновныеДанные_); ЗаполнитьURLОбъекта(ОсновныеДанные_, Наименование, Бакет, , Каталог); Подпись = СоздатьПодписьURL(ОсновныеДанные_, "PUT", ВремяЖизни, Заголовки); URL = ОсновныеДанные_["URL"] + Подпись; Возврат URL; КонецФункции #КонецОбласти #КонецОбласти #Область СлужебныеПроцедурыИФункции #Область Авторизация Функция СоздатьПодписьURL(Знач СтруктураДанных, Знач Метод, Знач ВремяЖизни, Знач Заголовки) AccessKey = СтруктураДанных["AccessKey"]; SecretKey = СтруктураДанных["SecretKey"]; Region = СтруктураДанных["Region"]; Service = СтруктураДанных["Service"]; URL = СтруктураДанных["URL"]; РазбитыйURL = OPI_Инструменты.РазбитьURL(URL); Домен = РазбитыйURL["Домен"]; Адрес = РазбитыйURL["Адрес"]; ДопЗаголовки = Новый Структура("Host", Домен); ДобавитьДополнительныеЗаголовки(Заголовки, ДопЗаголовки); ТекущаяДата = ТекущаяУниверсальнаяДата(); КлючПодписи = ПолучитьКлючПодписи(SecretKey, Region, Service, ТекущаяДата); Скоуп = СоздатьСкоуп(Region, Service, ТекущаяДата); ВременнаяМетка = OPI_Инструменты.ВременнаяМеткаISO(ТекущаяДата); КлючиЗаголовков = ПолучитьСтрокуКлючейЗаголовков(Заголовки); Основа = КодироватьСтроку(AccessKey + "/" + Скоуп, СпособКодированияСтроки.КодировкаURL); СтрокаЗаголовков = ПолучитьСтрокуЗаголовков(Заголовки); СтрокаХеша = "UNSIGNED-PAYLOAD"; ПараметрыURL = Новый ТаблицаЗначений; OPI_Инструменты.ДобавитьКлючЗначение(ПараметрыURL, "X-Amz-Algorithm" , "AWS4-HMAC-SHA256"); OPI_Инструменты.ДобавитьКлючЗначение(ПараметрыURL, "X-Amz-Credential" , Основа); OPI_Инструменты.ДобавитьКлючЗначение(ПараметрыURL, "X-Amz-Date" , ВременнаяМетка); OPI_Инструменты.ДобавитьКлючЗначение(ПараметрыURL, "X-Amz-Expires" , ВремяЖизни); OPI_Инструменты.ДобавитьКлючЗначение(ПараметрыURL, "X-Amz-SignedHeaders", КлючиЗаголовков); ПараметрыСтрокой = OPI_Инструменты.ПараметрыЗапросаВСтроку(ПараметрыURL); ПараметрыСтрокой = Прав(ПараметрыСтрокой, СтрДлина(ПараметрыСтрокой) - 1); ШаблонЗапроса = ""; ЧислоЧастей = 6; Для Н = 1 По ЧислоЧастей Цикл ШаблонЗапроса = ШаблонЗапроса + "%" + Строка(Н) + ?(Н = ЧислоЧастей, "", Символы.ПС); КонецЦикла; КаноническийЗапрос = СтрШаблон(ШаблонЗапроса , Метод , Адрес , ПараметрыСтрокой , СтрокаЗаголовков , КлючиЗаголовков , СтрокаХеша); СтрокаДляПодписи = СоздатьСтрокуПодписи(КаноническийЗапрос, Скоуп, ТекущаяДата); Сигнатура = OPI_Криптография.HMAC(КлючПодписи, СтрокаДляПодписи, "SHA256"); Сигнатура = нРег(ПолучитьHexСтрокуИзДвоичныхДанных(Сигнатура)); OPI_Инструменты.ДобавитьКлючЗначение(ПараметрыURL, "X-Amz-Signature", Сигнатура); ПодписьURL = OPI_Инструменты.ПараметрыЗапросаВСтроку(ПараметрыURL); Возврат ПодписьURL; КонецФункции Функция ПолучитьКлючПодписи(Знач СекретныйКлюч, Знач Регион, Знач Сервис, Знач ТекущаяДата) СекретныйКлюч = ПолучитьДвоичныеДанныеИзСтроки("AWS4" + СекретныйКлюч); ДанныеДата = ПолучитьДвоичныеДанныеИзСтроки(Формат(ТекущаяДата, "ДФ=yyyyMMdd;")); Регион = ПолучитьДвоичныеДанныеИзСтроки(Регион); Сервис = ПолучитьДвоичныеДанныеИзСтроки(Сервис); AWSЗапрос = ПолучитьДвоичныеДанныеИзСтроки("aws4_request"); Sha256_ = "SHA256"; КлючДанных = OPI_Криптография.HMAC(СекретныйКлюч, ДанныеДата, Sha256_); КлючРегиона = OPI_Криптография.HMAC(КлючДанных, Регион, Sha256_); КлючСервиса = OPI_Криптография.HMAC(КлючРегиона, Сервис, Sha256_); ФинальныйКлюч = OPI_Криптография.HMAC(КлючСервиса, AWSЗапрос, Sha256_); Возврат ФинальныйКлюч; КонецФункции Функция СоздатьСкоуп(Знач Регион, Знач Сервис, Знач ТекущаяДата) ДатаОбычная = Формат(ТекущаяДата, "ДФ=yyyyMMdd;"); Скоуп = Новый Массив; Скоуп.Добавить(ДатаОбычная); Скоуп.Добавить(Регион); Скоуп.Добавить(Сервис); Скоуп.Добавить("aws4_request"); СкоупСтрокой = СтрСоединить(Скоуп, "/"); Возврат СкоупСтрокой; КонецФункции Функция СоздатьСтрокуПодписи(Знач КаноническийЗапрос, Знач Скоуп, Знач ТекущаяДата) ШаблонСтроки = ""; Алгоритм = "AWS4-HMAC-SHA256"; ДатаISO = OPI_Инструменты.ВременнаяМеткаISO(ТекущаяДата); ЧислоЧастей = 4; КаноническийЗапрос = ПолучитьДвоичныеДанныеИзСтроки(КаноническийЗапрос); КаноническийЗапрос = OPI_Криптография.Хеш(КаноническийЗапрос, ХешФункция.SHA256); КаноническийЗапрос = нРег(ПолучитьHexСтрокуИзДвоичныхДанных(КаноническийЗапрос)); Для Н = 1 По ЧислоЧастей Цикл ШаблонСтроки = ШаблонСтроки + "%" + Строка(Н) + ?(Н = ЧислоЧастей, "", Символы.ПС); КонецЦикла; СтрокаПодписи = СтрШаблон(ШаблонСтроки, Алгоритм, ДатаISO, Скоуп, КаноническийЗапрос); СтрокаПодписи = ПолучитьДвоичныеДанныеИзСтроки(СтрокаПодписи); Возврат СтрокаПодписи; КонецФункции Функция ПолучитьСтрокуЗаголовков(Знач Заголовки) СписокЗаголовков = Новый СписокЗначений; Для Каждого Заголовок Из Заголовки Цикл ТекущийКлюч = Заголовок.Ключ; ТекущийКлючН = нРег(ТекущийКлюч); Если Не СтрНачинаетсяС(ТекущийКлючН, "host") И Не СтрНачинаетсяС(ТекущийКлючН, "x-amz") Тогда Продолжить; КонецЕсли; СтрокаЗаголовка = нРег(ТекущийКлюч) + ":" + Заголовок.Значение; СписокЗаголовков.Добавить(СтрокаЗаголовка); КонецЦикла; СписокЗаголовков.СортироватьПоЗначению(); СтрокаЗаголовков = СтрСоединить(СписокЗаголовков.ВыгрузитьЗначения(), Символы.ПС); СтрокаЗаголовков = СтрокаЗаголовков + Символы.ПС; Возврат СтрокаЗаголовков; КонецФункции Функция ПолучитьСтрокуКлючейЗаголовков(Знач Заголовки) СписокЗаголовков = Новый СписокЗначений; Для Каждого Заголовок Из Заголовки Цикл ТекущийКлюч = Заголовок.Ключ; ТекущийКлючН = нРег(ТекущийКлюч); Если Не СтрНачинаетсяС(ТекущийКлючН, "host") И Не СтрНачинаетсяС(ТекущийКлючН, "x-amz") Тогда Продолжить; КонецЕсли; СтрокаЗаголовка = нРег(ТекущийКлюч); СписокЗаголовков.Добавить(СтрокаЗаголовка); КонецЦикла; СписокЗаголовков.СортироватьПоЗначению(); СтрокаЗаголовков = СтрСоединить(СписокЗаголовков.ВыгрузитьЗначения(), ";"); Возврат СтрокаЗаголовков; КонецФункции Функция ПолучитьURLСервиса(ОсновныеДанные) OPI_ПреобразованиеТипов.ПолучитьКоллекцию(ОсновныеДанные); Если ТипЗнч(ОсновныеДанные) = Тип("Массив") Тогда ВызватьИсключение "Ошибка получения авторизационных данных из структуры"; КонецЕсли; URL = ОсновныеДанные["URL"]; OPI_ПреобразованиеТипов.ПолучитьСтроку(URL); Если Не СтрЗаканчиваетсяНа(URL, "/") Тогда URL = URL + "/"; КонецЕсли; Возврат URL; КонецФункции #КонецОбласти #Область Прочее Функция ОтправитьЗапрос(Знач Метод , Знач ОсновныеДанные , Знач Тело = Неопределено , Знач ОжидаютсяДвоичные = Ложь , Знач Заголовки = Неопределено) ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); ПроверитьОсновныеДанные(ОсновныеДанные_); AccessKey = ОсновныеДанные_["AccessKey"]; SecretKey = ОсновныеДанные_["SecretKey"]; Region = ОсновныеДанные_["Region"]; Service = ОсновныеДанные_["Service"]; URL = ОсновныеДанные_["URL"]; Ответ = OPI_ЗапросыHTTP.НовыйЗапрос() .Инициализировать(URL) .УстановитьЗаголовки(Заголовки) .УстановитьДвоичноеТело(Тело) .ДобавитьAWS4Авторизацию(AccessKey, SecretKey, Region, Service) .ОбработатьЗапрос(Метод); HTTPОтвет = Ответ.ВернутьОтвет(Ложь, Истина); ТелоОтвета = ?(ОжидаютсяДвоичные , Ответ.ВернутьОтветКакДвоичныеДанные(Ложь, Истина) , Ответ.ВернутьОтветКакСтроку(Ложь, Истина)); Ответ = ОформитьОтвет(HTTPОтвет, ТелоОтвета); Возврат Ответ; КонецФункции Функция УправлениеБакетом(Знач Имя, Знач ОсновныеДанные, Знач Каталог, Знач Метод, Знач Заголовки) ОсновныеДанные_ = OPI_Инструменты.КопироватьКоллекцию(ОсновныеДанные); URL = ПолучитьURLСервиса(ОсновныеДанные_); URL = СформироватьURLБакета(URL, Имя, Каталог); ОсновныеДанные_.Вставить("URL", URL); Ответ = ОтправитьЗапросБезТела(Метод, ОсновныеДанные_, , Заголовки); Возврат Ответ; КонецФункции Функция ПолучитьОбъектЧастями(Знач ОсновныеДанные , Знач Заголовки , Знач ПутьСохранения , Знач Размеры) ОбщийРазмер = Размеры["object"]; РазмерУчастка = Размеры["chunk"]; ШаблонЗаголовка = "bytes=%1-%2"; НачалоУчастка = 0; Попытки = 3; МассивЗаголовков = Новый Массив; Пока НачалоУчастка < ОбщийРазмер - РазмерУчастка Цикл КонецУчастка = НачалоУчастка + РазмерУчастка - 1; НачалоСтр = OPI_Инструменты.ЧислоВСтроку(НачалоУчастка); КонецСтр = OPI_Инструменты.ЧислоВСтроку(КонецУчастка); Заголовок = СтрШаблон(ШаблонЗаголовка, НачалоСтр, КонецСтр); МассивЗаголовков.Добавить(Новый Структура("Заголовок,Позиция", Заголовок, КонецСтр)); НачалоУчастка = КонецУчастка + 1; КонецЦикла; Если НачалоУчастка < ОбщийРазмер Тогда Заголовок = "bytes=" + OPI_Инструменты.ЧислоВСтроку(НачалоУчастка) + "-"; СтруктураИнформации = Новый Структура("Заголовок,Позиция", Заголовок, ОбщийРазмер); МассивЗаголовков.Добавить(СтруктураИнформации); КонецЕсли; ПотокФайла = OPI_Инструменты.СоздатьПоток(ПутьСохранения); ЗаписьФайла = Новый ЗаписьДанных(ПотокФайла); Для Каждого ТекущийНабор Из МассивЗаголовков Цикл Для Н = 1 По Попытки Цикл Попытка ЗаголовокУчастка = ТекущийНабор["Заголовок"]; ТекущаяПозиция = ТекущийНабор["Позиция"]; ЗаголовокИсточника = Новый Соответствие(); ЗаголовокИсточника.Вставить("Range", ЗаголовокУчастка); ДобавитьДополнительныеЗаголовки(Заголовки, ЗаголовокИсточника); ПромежуточныйРезультат = ПолучитьОбъектЦеликом(ОсновныеДанные, ЗаголовокИсточника); ЗаписьФайла.Записать(ПромежуточныйРезультат); КБайт = 1024; МБайт = КБайт * КБайт; OPI_Инструменты.ИнформацияОПрогрессе(ТекущаяПозиция, ОбщийРазмер, "МБ", МБайт); // !OInt ВыполнитьСборкуМусора(); // !OInt ОсвободитьОбъект(ПромежуточныйРезультат); Прервать; Исключение Если Н = Попытки Тогда // !OInt Сообщить(ОписаниеОшибки()); ВызватьИсключение "Не удалось получить файл!"; Иначе // !OInt Сообщить("Ошибка загрузки участка " + Строка(Н) + "/" + Строка(Попытки)); Продолжить; КонецЕсли; КонецПопытки; КонецЦикла; КонецЦикла; ЗаписьФайла.Закрыть(); ПолученныйОбъект = ЗакрытьПотокИПолучитьДанные(ПотокФайла, ПутьСохранения); Возврат ПолученныйОбъект; КонецФункции Функция ПолучитьОбъектЦеликом(Знач ОсновныеДанные , Знач Заголовки , Знач ПутьСохранения = "") Ответ = ОтправитьЗапросБезТела("GET", ОсновныеДанные, Истина, Заголовки); Если ЗначениеЗаполнено(ПутьСохранения) Тогда Ответ.Записать(ПутьСохранения); ФайлОтвета = Новый Файл(ПутьСохранения); Возврат ФайлОтвета.ПолноеИмя; Иначе Возврат Ответ; КонецЕсли; КонецФункции Функция ЗагрузитьОбъектЧастями(Знач Наименование , Знач Бакет , Знач Содержимое , Знач ОсновныеДанные , Знач Заголовки , Знач Размеры , Знач Каталог = "") OPI_ПреобразованиеТипов.ПолучитьДвоичныеИлиПоток(Содержимое); НачалоЗагрузки = ИнициализироватьЗагрузкуЧастями(Наименование, Бакет, ОсновныеДанные, Заголовки, Каталог); ПолеID = "response.InitiateMultipartUploadResult.UploadId"; IDЗагрузки = Неопределено; ОбщийРазмер = Размеры["object"]; РазмерУчастка = Размеры["chunk"]; ПрочитаноБайт = 0; НомерЧасти = 1; Если Не OPI_Инструменты.ПолеКоллекцииСуществует(НачалоЗагрузки, ПолеID, IDЗагрузки) Тогда Возврат НачалоЗагрузки; КонецЕсли; ЧтениеДанных = Новый ЧтениеДанных(Содержимое); ИсходныйПоток = ЧтениеДанных.ИсходныйПоток(); Ответ = Новый Соответствие; МассивТегов = Новый Массив; Ошибка = Ложь; Попытки = 3; ПоследнийКодУспеха = 299; Пока ПрочитаноБайт < ОбщийРазмер Цикл Для Н = 1 По Попытки Цикл Попытка Результат = ЧтениеДанных.Прочитать(РазмерУчастка); ТекущиеДанные = Результат.ПолучитьДвоичныеДанные(); Если ТекущиеДанные.Размер() = 0 Тогда Прервать; КонецЕсли; Ответ = ЗагрузитьЧастьОбъекта(Наименование , Бакет , ОсновныеДанные , IDЗагрузки , НомерЧасти , ТекущиеДанные , Каталог); Если Ответ["status"] > ПоследнийКодУспеха Тогда ВызватьИсключение "Сервер вернул статус " + Строка(Ответ["status"]); КонецЕсли; ПрочитаноБайт = ИсходныйПоток.ТекущаяПозиция(); ETag = Ответ["headers"]["Etag"]; ETag = ?(ETag = Неопределено, Ответ["headers"]["ETag"], ETag); МассивТегов.Добавить(ETag); КБайт = 1024; МБайт = КБайт * КБайт; OPI_Инструменты.ИнформацияОПрогрессе(ПрочитаноБайт, ОбщийРазмер, "МБ", МБайт); // !OInt ВыполнитьСборкуМусора(); // !OInt ОсвободитьОбъект(ТекущиеДанные); Прервать; Исключение Если Н = Попытки Тогда // !OInt Сообщить(OPI_Инструменты.JSONСтрокой(Ответ)); // !OInt Сообщить("Не удалось загрузить часть файла! Отмена загрузки ID:" + IDЗагрузки + "..."); Ошибка = Истина; Прервать; Иначе // !OInt Сообщить("Ошибка загрузки участка " + Строка(Н) + "/" + Строка(Попытки)); // !OInt Сообщить(ОписаниеОшибки()); Продолжить; КонецЕсли; КонецПопытки; КонецЦикла; НомерЧасти = НомерЧасти + 1; КонецЦикла; Если Ошибка Тогда Ответ = ОтменитьЗагрузкуЧастями(Наименование, Бакет, ОсновныеДанные, IDЗагрузки, , Каталог); Иначе Ответ = ЗавершитьЗагрузкуЧастями(Наименование, Бакет, ОсновныеДанные, IDЗагрузки, МассивТегов, , Каталог); КонецЕсли; Возврат Ответ; КонецФункции Функция ОформитьОтвет(Знач Ответ, Знач Тело) Статус = Ответ.КодСостояния; Заголовки = Ответ.Заголовки; ПоследнийКодУспеха = 299; Если ТипЗнч(Тело) = Тип("Строка") Или Статус > ПоследнийКодУспеха Тогда ДанныеОтвета = Новый Структура; ДанныеТела = Новый Структура; ТелоОтветаИзначальное = ?(ТипЗнч(Тело) = Тип("Строка"), Тело, Base64Строка(Тело)); ТелоОтветаДляОбработки = СокрЛП(ТелоОтветаИзначальное); Если ЗначениеЗаполнено(ТелоОтветаДляОбработки) Тогда Попытка ДанныеТела = OPI_Инструменты.ОбработатьXML(ТелоОтветаДляОбработки); Исключение ДанныеТела.Вставить("notValidXMLMessage", ТелоОтветаИзначальное); КонецПопытки; КонецЕсли; ДанныеОтвета = Новый Структура; ДанныеОтвета.Вставить("status" , Статус); ДанныеОтвета.Вставить("response", ДанныеТела); ДанныеОтвета.Вставить("headers" , Заголовки); Иначе ДанныеОтвета = Тело; КонецЕсли; Возврат ДанныеОтвета; КонецФункции Функция СформироватьURLБакета(Знач URL, Знач Имя, Знач Каталог) OPI_ПреобразованиеТипов.ПолучитьСтроку(Имя); OPI_ПреобразованиеТипов.ПолучитьБулево(Каталог); Признак = "://"; Если Каталог Тогда URL = URL + Имя; Иначе Если СтрНайти(URL, Признак) Тогда URL = СтрЗаменить(URL, Признак, Признак + Имя + "."); Иначе URL = Имя + "." + URL; КонецЕсли; КонецЕсли; Если Не СтрЗаканчиваетсяНа(URL, "/") Тогда URL = URL + "/"; КонецЕсли; Возврат URL; КонецФункции Функция СформироватьСтруктуруТегов(Знач Теги) ТекстОшибки = "Некорректный формат тегов. Ожидается коллекция ключ-значение"; OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Теги, ТекстОшибки); МассивТегов = Новый Массив; Для Каждого Тег Из Теги Цикл СтруктураТега = Новый Структура; СтруктураТега.Вставить("Key" , Строка(Тег.Ключ)); СтруктураТега.Вставить("Value", Строка(Тег.Значение)); МассивТегов.Добавить(Новый Структура("Tag", СтруктураТега)); КонецЦикла; ФинальнаяСтруктура = Новый Структура; НаборТегов = Новый Структура; НаборТегов.Вставить("TagSet", МассивТегов); ФинальнаяСтруктура.Вставить("Tagging", НаборТегов); Возврат ФинальнаяСтруктура; КонецФункции Функция СформироватьСтруктуруНастроекВерсионирования(Знач Статус, Знач УдалениеMFA) СтруктураНастроек = Новый Структура; Если ЗначениеЗаполнено(Статус) Тогда OPI_ПреобразованиеТипов.ПолучитьБулево(Статус); СтруктураНастроек.Вставить("Status", ?(Статус, "Enabled", "Suspended")); КонецЕсли; Если ЗначениеЗаполнено(УдалениеMFA) Тогда OPI_ПреобразованиеТипов.ПолучитьБулево(УдалениеMFA); СтруктураНастроек.Вставить("MfaDelete", ?(УдалениеMFA, "Enabled", "Disabled")); КонецЕсли; ФинальнаяСтруктура = Новый Структура("VersioningConfiguration", СтруктураНастроек); Возврат ФинальнаяСтруктура; КонецФункции Функция ПолучитьРазмерСодержимого(Знач Содержимое) Если ТипЗнч(Содержимое) = Тип("Строка") Тогда ФайлСодержимого = Новый Файл(Содержимое); Возврат ФайлСодержимого.Размер(); Иначе Возврат Содержимое.Размер(); КонецЕсли; КонецФункции Функция ЗакрытьПотокИПолучитьДанные(Знач ПотокФайла, Знач ПутьСохранения) Если ТипЗнч(ПотокФайла) = Тип("ПотокВПамяти") Тогда Возврат ПотокФайла.ЗакрытьИПолучитьДвоичныеДанные(); Иначе ПотокФайла.Закрыть(); ФайлОтвета = Новый Файл(ПутьСохранения); Возврат ФайлОтвета.ПолноеИмя; КонецЕсли; КонецФункции Процедура ПроверитьОсновныеДанные(ОсновныеДанные) ТекстОшибки = "Ошибка получения авторизационных данных из структуры"; OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(ОсновныеДанные, ТекстОшибки); МассивНеобходимыхПолей = Новый Массив; МассивНеобходимыхПолей.Добавить("AccessKey"); МассивНеобходимыхПолей.Добавить("SecretKey"); МассивНеобходимыхПолей.Добавить("Region"); МассивНеобходимыхПолей.Добавить("Service"); МассивНеобходимыхПолей.Добавить("URL"); ОтсутствующиеПоля = OPI_Инструменты.НайтиОтсутствующиеПоляКоллекции(ОсновныеДанные, МассивНеобходимыхПолей); Если ОтсутствующиеПоля.Количество() > 0 Тогда ВызватьИсключение "Отсутствуют необходимые данные авторизации: " + СтрСоединить(ОтсутствующиеПоля, ", "); КонецЕсли; КонецПроцедуры Процедура ДобавитьДополнительныеЗаголовки(Приемник, Знач Заголовки) Если Не ЗначениеЗаполнено(Заголовки) Тогда Возврат; КонецЕсли; ТипПриемника = ТипЗнч(Приемник); ТекстОшибки = "Ошибка установки дополнительных заголовков"; OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Заголовки, ТекстОшибки); Если ТипПриемника = Тип("HTTPЗапрос") Тогда Для Каждого Заголовок Из Заголовки Цикл Приемник.Заголовки.Вставить(Заголовок.Ключ, Заголовок.Значение); КонецЦикла; Иначе Если Не ЗначениеЗаполнено(Приемник) Тогда Приемник = Новый Соответствие; Иначе OPI_ПреобразованиеТипов.ПолучитьКоллекциюКлючИЗначение(Приемник, ТекстОшибки); КонецЕсли; Для Каждого Заголовок Из Заголовки Цикл Приемник.Вставить(Заголовок.Ключ, Заголовок.Значение); КонецЦикла; КонецЕсли; КонецПроцедуры Процедура ЗаполнитьURLОбъекта(ОсновныеДанные, Наименование, Бакет, Версия = "", Каталог = Ложь) OPI_ПреобразованиеТипов.ПолучитьСтроку(Наименование); URL = ПолучитьURLСервиса(ОсновныеДанные); URL = СформироватьURLБакета(URL, Бакет, Каталог); URL = URL + Наименование; Если ЗначениеЗаполнено(Версия) Тогда OPI_ПреобразованиеТипов.ПолучитьСтроку(Версия); URL = URL + "?versionId=" + Версия; КонецЕсли; ОсновныеДанные.Вставить("URL", URL); КонецПроцедуры #КонецОбласти #КонецОбласти