1
0
mirror of https://github.com/Bayselonarrend/OpenIntegrations.git synced 2025-11-25 22:12:29 +02:00
Files
OpenIntegrations/XML/CommonModules/OPI_S3/Ext/Module.bsl
Vitaly the Alpaca (bot) cdef2d02ab Main build (Jenkins)
2025-10-21 21:43:05 +03:00

1972 lines
119 KiB
Plaintext

// 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);
КонецПроцедуры
#КонецОбласти
#КонецОбласти