Skip to content

Commit

Permalink
Загрузка больших файлов на GD
Browse files Browse the repository at this point in the history
  • Loading branch information
Bayselonarrend committed Apr 4, 2024
1 parent 87437fa commit 2bccc4a
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 18 deletions.
122 changes: 115 additions & 7 deletions OPI/src/CommonModules/OPI_GoogleDrive/Module.bsl
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,7 @@
OPI_ПреобразованиеТипов.ПолучитьКоллекцию(Описание);
КонецЕсли;

СоответствиеФайла = Новый Соответствие;
MimeType = "mimeType";
MimeType = "mimeType";

Если ЗначениеЗаполнено(Идентификатор) Тогда
MIME = ПолучитьИнформациюОбОбъекте(Токен, Идентификатор)[MimeType];
Expand All @@ -528,25 +527,134 @@
Описание = Новый Соответствие;
КонецЕсли;

Заголовки = 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/" + Идентификатор);
Ответ = OPI_Инструменты.PatchMultipartRelated(URL, Описание, СоответствиеФайла, Заголовки);
Иначе
Ответ = 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;

// !OInt СтрТекущаяПозиция = OPI_Инструменты.ЧислоВСтроку(ТекущаяПозиция);
// !OInt Процент = Строка(Цел(ТекущаяПозиция / ОбщийРазмер) * 100);

// !OInt Сообщить(СтрТекущаяПозиция + "/" + СтрОбщийРазмер + " (" + Процент + ")");

КонецЦикла;

Возврат Ответ;

Expand Down
38 changes: 27 additions & 11 deletions OPI/src/CommonModules/OPI_Инструменты/Module.bsl
Original file line number Diff line number Diff line change
Expand Up @@ -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, ПолныйОтвет);
КонецФункции

#КонецОбласти
Expand Down Expand Up @@ -300,7 +300,7 @@

#Область СлужебныеПроцедурыИФункции

Функция ВыполнитьЗапросСТелом(Знач URL, Знач Вид, Знач Параметры = "", Знач ДопЗаголовки = "", Знач JSON = Истина)
Функция ВыполнитьЗапросСТелом(Знач URL, Знач Вид, Знач Параметры = "", Знач ДопЗаголовки = "", Знач JSON = Истина, Знач ПолныйОтвет = Ложь)

Если Не ЗначениеЗаполнено(Параметры) Тогда
Параметры = Новый Структура;
Expand All @@ -321,7 +321,7 @@
Если ЭтоПереадресация(Ответ) Тогда
Ответ = ВыполнитьЗапросСТелом(Ответ.Заголовки["Location"], Вид, Параметры, ДопЗаголовки, JSON);
Иначе
ОбработатьОтвет(Ответ);
ОбработатьОтвет(Ответ, ПолныйОтвет);
КонецЕсли;

Возврат Ответ;
Expand Down Expand Up @@ -485,13 +485,19 @@
Переадресация = 300;
Ошибка = 400;

ЭтоПереадресация = Ответ.КодСостояния >= Переадресация И Ответ.КодСостояния < Ошибка;
ЭтоПереадресация = Ответ.КодСостояния >= Переадресация
И Ответ.КодСостояния < Ошибка
И ЗначениеЗаполнено(Ответ.Заголовки["Location"]);

Возврат ЭтоПереадресация;

КонецФункции

Процедура ОбработатьОтвет(Ответ)
Процедура ОбработатьОтвет(Ответ, Знач ПолныйОтвет = Ложь)

Если ПолныйОтвет Тогда
Возврат;
КонецЕсли;

GZip = "gzip";
НужнаРаспаковка =
Expand All @@ -518,14 +524,24 @@

Процедура УстановитьТелоЗапроса(Запрос, Знач Параметры, Знач JSON)

Коллекция = ТипЗнч(Параметры) = Тип("Структура")
Или ТипЗнч(Параметры) = Тип("Соответствие")
Или ТипЗнч(Параметры) = Тип("Массив");

Если JSON Тогда
Данные = JSONСтрокой(Параметры);
ИначеЕсли Не Коллекция Тогда
Данные = Параметры;
Иначе
СтрокаПараметров = ПараметрыЗапросаВСтроку(Параметры);
Данные = Прав(СтрокаПараметров, СтрДлина(СтрокаПараметров) - 1);
КонецЕсли;

Запрос.УстановитьТелоИзСтроки(Данные);
Если ТипЗнч(Данные) = Тип("Строка") Тогда
Запрос.УстановитьТелоИзСтроки(Данные);
Иначе
Запрос.УстановитьТелоИзДвоичныхДанных(Данные);
КонецЕсли;

КонецПроцедуры

Expand Down

0 comments on commit 2bccc4a

Please sign in to comment.