From 7e9582db84c4035de7858a52dcca2fd3df205a53 Mon Sep 17 00:00:00 2001 From: Vitaly the Alpaca Date: Thu, 4 Apr 2024 12:04:27 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=BE=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20OPI=20->=20OInt=20?= =?UTF-8?q?(workflow)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OInt/core/Modules/OPI_GoogleDrive.os | 122 +++++++++++++++++- .../internal/Modules/OPI_Инструменты.os | 38 ++++-- 2 files changed, 142 insertions(+), 18 deletions(-) diff --git a/OInt/core/Modules/OPI_GoogleDrive.os b/OInt/core/Modules/OPI_GoogleDrive.os index 5490ef5084..bf59a61d21 100644 --- a/OInt/core/Modules/OPI_GoogleDrive.os +++ b/OInt/core/Modules/OPI_GoogleDrive.os @@ -515,8 +515,7 @@ OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Описание); КонецЕсли; - СоответствиеФайла = Новый Соответствие; - MimeType = "mimeType"; + MimeType = "mimeType"; Если ЗначениеЗаполнено(Идентификатор) Тогда MIME = ПолучитьИнформациюОбОбъекте(Токен, Идентификатор)[MimeType]; @@ -528,18 +527,35 @@ Описание = Новый Соответствие; КонецЕсли; - Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен); - URL = "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"; + Заголовки = OPI_GoogleWorkspace.ПолучитьЗаголовокАвторизации(Токен); + СформироватьПараметрыЗагрузкиФайла(Описание); + ОписаниеJSON = OPI_Инструменты.JSONСтрокой(Описание); + Если ЗначениеЗаполнено(Файл) Тогда + СоответствиеФайла = Новый Соответствие; OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Файл); СоответствиеФайла.Вставить(Файл, MIME); - КонецЕсли; + Размер = Файл.Размер(); + РазмерЧасти = 536870912; - СформироватьПараметрыЗагрузкиФайла(Описание); - Описание = OPI_Инструменты.JSONСтрокой(Описание); + Если Размер < РазмерЧасти * 2 Тогда + Ответ = ЗагрузитьМалыйФайл(ОписаниеJSON, СоответствиеФайла, Заголовки, Идентификатор); + Иначе + Ответ = ЗагрузитьБольшойФайл(Описание, СоответствиеФайла, Заголовки, Идентификатор); + КонецЕсли; + + КонецЕсли; + + Возврат Ответ; + +КонецФункции + +Функция ЗагрузитьМалыйФайл(Знач Описание, Знач СоответствиеФайла, Знач Заголовки, Знач Идентификатор = "") + + URL = "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"; Если ЗначениеЗаполнено(Идентификатор) Тогда URL = СтрЗаменить(URL, "/files", "/files/" + Идентификатор); @@ -547,6 +563,98 @@ Иначе Ответ = OPI_Инструменты.PostMultipartRelated(URL, Описание, СоответствиеФайла, Заголовки); КонецЕсли; + + Возврат Ответ; + +КонецФункции + +Функция ЗагрузитьБольшойФайл(Знач Описание, Знач СоответствиеФайла, Знач Заголовки, Знач Идентификатор = "") + + Для Каждого Файл Из СоответствиеФайла Цикл + Двоичные = Файл.Ключ; + Прервать; + КонецЦикла; + + РазмерЧасти = 536870912; + URL = "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable"; + Ответ = OPI_Инструменты.Post(URL, Описание, Заголовки, Истина, Истина); + + АдресЗагрузки = Ответ.Заголовки["Location"]; + + Если Не ЗначениеЗаполнено(АдресЗагрузки) Тогда + Возврат Ответ; + КонецЕсли; + + Поток = Двоичные.ОткрытьПотокДляЧтения(); + ЧтениеДанных = Новый ЧтениеДанных(Поток); + ТекущаяПозиция = 0; + ОбщийРазмер = Поток.Размер(); + СтрОбщийРазмер = OPI_Инструменты.ЧислоВСтроку(ОбщийРазмер); + + Пока Поток.ТекущаяПозиция() < ОбщийРазмер - 1 Цикл + + Поток.Перейти(ТекущаяПозиция, ПозицияВПотоке.Начало); + Результат = ЧтениеДанных.Прочитать(РазмерЧасти); + ТекущиеДанные = Результат.ПолучитьДвоичныеДанные(); + РазмерТекущих = ТекущиеДанные.Размер(); + СледующаяПозиция = ТекущаяПозиция + РазмерТекущих - 1; + + Если Не ЗначениеЗаполнено(ТекущиеДанные) Тогда + Прервать; + КонецЕсли; + + ЗаголовокПотока = "bytes " + + OPI_Инструменты.ЧислоВСтроку(ТекущаяПозиция) + + "-" + + OPI_Инструменты.ЧислоВСтроку(СледующаяПозиция) + + "/" + + СтрОбщийРазмер; + + ДопЗаголовки = Новый Соответствие; + ДопЗаголовки.Вставить("Content-Length", OPI_Инструменты.ЧислоВСтроку(РазмерТекущих)); + ДопЗаголовки.Вставить("Content-Range" , ЗаголовокПотока); + ДопЗаголовки.Вставить("Content-Type" , "application/octet-stream"); + + Ответ = OPI_Инструменты.Put(АдресЗагрузки, ТекущиеДанные, ДопЗаголовки, Ложь, Истина); + + Если Ответ.КодСостояния >= 400 И Ответ.КодСостояния < 600 Тогда + + ЗаголовокПотока = "bytes */" + СтрОбщийРазмер; + ДопЗаголовки.Вставить("Content-Range" , ЗаголовокПотока); + + ОтветПроверки = OPI_Инструменты.Put(АдресЗагрузки, "", ДопЗаголовки, Ложь, Истина); + + Если ОтветПроверки.КодСостояния >= 200 И ОтветПроверки.КодСостояния < 300 Тогда + Возврат ОтветПроверки; + ИначеЕсли ОтветПроверки.КодСостояния = 308 Тогда + ЗагруженныеДанные = Ответ.Заголовки["Range"]; + Иначе + Возврат Ответ; + КонецЕсли; + + Иначе + ЗагруженныеДанные = Ответ.Заголовки["Range"]; + КонецЕсли; + + Если Не ЗначениеЗаполнено(ЗагруженныеДанные) Тогда + Возврат Ответ; + КонецЕсли; + + ЗагруженныеДанные = СтрЗаменить(ЗагруженныеДанные, "bytes=", ""); + МассивИнформации = СтрРазделить(ЗагруженныеДанные, "-", Ложь); + + Если Не МассивИнформации.Количество() = 2 Тогда + Возврат Ответ; + КонецЕсли; + + ТекущаяПозиция = Число(МассивИнформации[1]) + 1; + + СтрТекущаяПозиция = OPI_Инструменты.ЧислоВСтроку(ТекущаяПозиция); + Процент = Строка(Цел(ТекущаяПозиция / ОбщийРазмер) * 100); + + Сообщить(СтрТекущаяПозиция + "/" + СтрОбщийРазмер + " (" + Процент + ")"); + + КонецЦикла; Возврат Ответ; diff --git a/OInt/tools/Modules/internal/Modules/OPI_Инструменты.os b/OInt/tools/Modules/internal/Modules/OPI_Инструменты.os index af1580cd6b..dab808bd4a 100644 --- a/OInt/tools/Modules/internal/Modules/OPI_Инструменты.os +++ b/OInt/tools/Modules/internal/Modules/OPI_Инструменты.os @@ -48,16 +48,16 @@ #Область ЗапросыСТелом -Функция Post(Знач URL, Знач Параметры = "", Знач ДопЗаголовки = "", Знач JSON = Истина) Экспорт - Возврат ВыполнитьЗапросСТелом(URL, "POST", Параметры, ДопЗаголовки, JSON); +Функция Post(Знач URL, Знач Параметры = "", Знач ДопЗаголовки = "", Знач JSON = Истина, Знач ПолныйОтвет = Ложь) Экспорт + Возврат ВыполнитьЗапросСТелом(URL, "POST", Параметры, ДопЗаголовки, JSON, ПолныйОтвет); КонецФункции -Функция Patch(Знач URL, Знач Параметры = "", Знач ДопЗаголовки = "", Знач JSON = Истина) Экспорт - Возврат ВыполнитьЗапросСТелом(URL, "PATCH", Параметры, ДопЗаголовки, JSON); +Функция Patch(Знач URL, Знач Параметры = "", Знач ДопЗаголовки = "", Знач JSON = Истина, Знач ПолныйОтвет = Ложь) Экспорт + Возврат ВыполнитьЗапросСТелом(URL, "PATCH", Параметры, ДопЗаголовки, JSON, ПолныйОтвет); КонецФункции -Функция Put(Знач URL, Знач Параметры = "", Знач ДопЗаголовки = "", Знач JSON = Истина) Экспорт - Возврат ВыполнитьЗапросСТелом(URL, "PUT", Параметры, ДопЗаголовки, JSON); +Функция Put(Знач URL, Знач Параметры = "", Знач ДопЗаголовки = "", Знач JSON = Истина, Знач ПолныйОтвет = Ложь) Экспорт + Возврат ВыполнитьЗапросСТелом(URL, "PUT", Параметры, ДопЗаголовки, JSON, ПолныйОтвет); КонецФункции #КонецОбласти @@ -300,7 +300,7 @@ #Область СлужебныеПроцедурыИФункции -Функция ВыполнитьЗапросСТелом(Знач URL, Знач Вид, Знач Параметры = "", Знач ДопЗаголовки = "", Знач JSON = Истина) +Функция ВыполнитьЗапросСТелом(Знач URL, Знач Вид, Знач Параметры = "", Знач ДопЗаголовки = "", Знач JSON = Истина, Знач ПолныйОтвет = Ложь) Если Не ЗначениеЗаполнено(Параметры) Тогда Параметры = Новый Структура; @@ -321,7 +321,7 @@ Если ЭтоПереадресация(Ответ) Тогда Ответ = ВыполнитьЗапросСТелом(Ответ.Заголовки["Location"], Вид, Параметры, ДопЗаголовки, JSON); Иначе - ОбработатьОтвет(Ответ); + ОбработатьОтвет(Ответ, ПолныйОтвет); КонецЕсли; Возврат Ответ; @@ -485,13 +485,19 @@ Переадресация = 300; Ошибка = 400; - ЭтоПереадресация = Ответ.КодСостояния >= Переадресация И Ответ.КодСостояния < Ошибка; + ЭтоПереадресация = Ответ.КодСостояния >= Переадресация + И Ответ.КодСостояния < Ошибка + И ЗначениеЗаполнено(Ответ.Заголовки["Location"]); Возврат ЭтоПереадресация; КонецФункции -Процедура ОбработатьОтвет(Ответ) +Процедура ОбработатьОтвет(Ответ, Знач ПолныйОтвет = Ложь) + + Если ПолныйОтвет Тогда + Возврат; + КонецЕсли; GZip = "gzip"; НужнаРаспаковка = @@ -518,14 +524,24 @@ Процедура УстановитьТелоЗапроса(Запрос, Знач Параметры, Знач JSON) + Коллекция = ТипЗнч(Параметры) = Тип("Структура") + Или ТипЗнч(Параметры) = Тип("Соответствие") + Или ТипЗнч(Параметры) = Тип("Массив"); + Если JSON Тогда Данные = JSONСтрокой(Параметры); + ИначеЕсли Не Коллекция Тогда + Данные = Параметры; Иначе СтрокаПараметров = ПараметрыЗапросаВСтроку(Параметры); Данные = Прав(СтрокаПараметров, СтрДлина(СтрокаПараметров) - 1); КонецЕсли; - Запрос.УстановитьТелоИзСтроки(Данные); + Если ТипЗнч(Данные) = Тип("Строка") Тогда + Запрос.УстановитьТелоИзСтроки(Данные); + Иначе + Запрос.УстановитьТелоИзДвоичныхДанных(Данные); + КонецЕсли; КонецПроцедуры