Передача больших пакетов через веб-сервисы

06.12.15

Интеграция - WEB-интеграция

Реализация механизма передачи больших пакетов через веб-сервисы. С его помощью передать файл размером в несколько гигабайт не составит проблем.

Скачать файлы

Наименование Файл Версия Размер
Передача больших пакетов через веб-сервисы частями
.cf 50,78Kb
98
.cf 0.1 98 Скачать бесплатно

Введение

Использование веб-сервисов платформы 1С:Предприятие набирает обороты для решения задач интеграции: обмены данными между базами, взаимодействие с мобильными или веб-приложениями и многое другое. Огромные возможности могут покрыть любые потребности при решении задач интеграции. Если Вы разрабатываете веб-сервисы для интеграции больших / высоконагруженных баз, то возможно описанная здесь проблема будет уже не новой.

Сегодня мы поговорим о передаче больших по размеру пакетов через веб-сервис, об ограничении веб-сервера и способе решения сложившейся ситуации. Суть проблемы заключается в следующем: стандартная конфигурация веб-сервера (будь то это IIS или Apache) содержат настройки по ограничению максимального размера пакета, который может быть обработан. Для IIS максимальный размер обрабатываемого сообщения ~30 МБ, а для Apache ~16 МБ. На счет Apache могу ошибаться, т.к. при установках стандартные настройки были разными.

При создании обменов данными через веб-сервисы размер отправляемого сообщения может быть значительно больше заданных ограничений. Например, при выгрузке из УПП 1.3 документа распределения косвенных расходов размер сформированного XML-файла в сжатом виде может достигать пару сотен мегабайт! В этом случае обмен просто встанет и сервер не сможет обработать входящее сообщение.

Рассмотрим два способа решения данной проблемы: с помощью настроек веб-сервера (на примере IIS) и с помощью разработанного механизма передачи сообщения по частям.

Быстрое решение

Если максимальный размер входящего сообщения нужно увеличить незначительно, то можно использовать быстрое решение, а именно изменить конфигурацию веб-сервера для обработки пакетов большего размера. Далее продемонстрировано изменение настроек для веб-сервера IIS несколькими способами:

 

1. Настройка через диспетчер служб IIS:

 

2. Изменение файла "web.config" в корне директории веб-приложения:


<system.webServer> 
   <security> 
      <requestFiltering> 
         <requestLimits maxAllowedContentLength="1048576000" /> 
      </requestFiltering> 
   </security> 
</system.webServer>

    •  

3. В командной строке выполнить:

cd c:\Windows\System32\inetsrv

appcmd set config "Default Web Site" -section:requestFiltering -requestLimits.maxAllowedContentLength:1048576000 -commitpath:apphost

Правильное решение
В случаях, когда размер передаваемого пакета значительно больше установленных по умолчанию ограничений, изменять конфигурацию веб-сервера не рекомендую. Если заставить принимать веб-сервер пакеты в несколько гигабайт, то это может значительно повлиять на его производительность / работоспособность. Лучше всего сделать передачу большого пакета частями. Далее рассмотрим простейшую реализацию такого механизма на платформе 1С:Предприятие с использованием веб-сервисов.


Реализация
В тестовой конфигурации сделан пример веб-сервиса для передачи пакетов частями. Общий принцип следующий: через веб-сервис передаются части файла и записываются в регистр сведений. Для всех частей файла присваивается некоторый GUID, по которому файл можно будет "склеить" обратно, а также порядковый номер части. Наглядно передачу файла размером в 170 МБ по частям с размером 5 МБ можно представить так:

Для промежуточного сохранения частей файла используется регистр сведений. Передача файла через веб-сервис выполняется с использованием XDTO-пакетов следующей структуры:

Фактически пакет дублирует структуру регистра сведений:

Далее представлен обработчик метода веб-сервиса:

Функция executeMethod(MessagePart)
	
	Ответ = ФабрикаXDTO.Создать(ФабрикаXDTO.Пакеты.Получить("http://www.develplatform.ru").Получить("MessagePartResponse"));
	
	Попытка
		РегистрыСведений.ПринятыеЧастиПакета.ЗафиксироватьПриемЧастиПакета(
			Новый УникальныйИдентификатор(MessagePart.MessageId),
			MessagePart.PartNumber,
			MessagePart.PartData,
			MessagePart.CountOfParts,
			MessagePart.MessageName,
			MessagePart.FileExtention,
			MessagePart.FileName,
			MessagePart.Size
		);
		Ответ.Success = Истина;
	Исключение
		Ответ.Success = Ложь;	
	КонецПопытки;
	
	Возврат Ответ;
	
КонецФункции

В качестве параметра метод веб-сервиса принимает объект с типом "MessagePartRequest" и передает из него данные в функцию "ЗафиксироватьПриемПакета". Эта функция сохраняет полученные через веб-сервис данные в базу:

Процедура ЗафиксироватьПриемЧастиПакета(Идентификатор, НомерЧасти, Данные, ВсегоЧастей, ИмяСообщения, РасширениеФайла, ИмяФайла, Размер) Экспорт
	
	Набор = РегистрыСведений.ПринятыеЧастиПакета.СоздатьНаборЗаписей();
	Набор.Отбор.ИдентификаторПакета.Установить(Идентификатор);
	Набор.Отбор.НомерЧасти.Установить(НомерЧасти);
	Запись = Набор.Добавить();
	Запись.ДанныеЧастиСообщения = Новый ХранилищеЗначения(Данные);
	Запись.ИдентификаторПакета = Идентификатор;
	Запись.НомерЧасти = НомерЧасти;
	Запись.ДатаСоздания = ТекущаяДата();
	Запись.ВсегоЧастей = ВсегоЧастей;
	Запись.ИмяСообщения = ИмяСообщения;
	Запись.РасширениеФайла = РасширениеФайла;
	Запись.ИмяФайла = ИмяФайла;
	Запись.РазмерФайла = Размер;
	Набор.Записать();
	
КонецПроцедуры

Также в конфигурацию добавлен общий модуль ОбменДаннымиWS с функциями отправки и получения файла. Функция отправки файла разбивает его на части и передает каждую часть отдельно, обращаясь к веб-сервису:

// Отправляет указанный файл на сервер через веб-сервис
//	Параметры:
//		1. ПутьКФайлуНаСервере - строка. Путь к передаваемому файлы на сервере
//		2. МаксимальныйРазмерЧастиПакетаБайт - число. Максимальный размер одной передаваемой части в байтах
//			По умолчанию 10 МБ.
//	Возвращаемое значение:
//		Уникальный идентификатор отправленного файла
//
Функция ОтправитьФайл(ПутьКФайлуНаСервере, МаксимальныйРазмерЧастиПакетаБайт = 10485760) Экспорт
	
	Slash = Символ(92); // Символ "/"
	ИдентификаторСообщения = Новый УникальныйИдентификатор;
	
	// Создаем временный каталог для сохранения в него частей исходного файла
	ВременныйКаталог = КаталогВременныхФайлов()+"SendingMessageWS"+Slash+ИдентификаторСообщения;
	СоздатьКаталог(ВременныйКаталог);
	// Разбиваем файл на части с помощью возможностей платформы
	РазделитьФайл(ПутьКФайлуНаСервере, МаксимальныйРазмерЧастиПакетаБайт, ВременныйКаталог);
	ВсеНайденныеФайлы = НайтиФайлы(ВременныйКаталог, "*");
	ИсходныйФайл = Новый Файл(ПутьКФайлуНаСервере);
	
	// Каждую часть файла отправляем через веб-сервис
	НомерЧасти = 1;
	Для Каждого Эл Из ВсеНайденныеФайлы Цикл
		Прокси = WSСсылки.SendMessageParts.СоздатьWSПрокси("http://www.develplatform.ru/SendBigMessage", "DevelPlatformRU", "DevelPlatformRUSoap");
		ТипОбъектаЗапроса = Прокси.ФабрикаXDTO.Пакеты.Получить("http://www.develplatform.ru").Получить("MessagePartRequest");
		ОбъектЗапроса = Прокси.ФабрикаXDTO.Создать(ТипОбъектаЗапроса);
		ОбъектЗапроса.MessageId = Строка(ИдентификаторСообщения);
		ОбъектЗапроса.PartNumber = НомерЧасти;
		ОбъектЗапроса.PartData = Новый ДвоичныеДанные(Эл.ПолноеИмя);
		ОбъектЗапроса.CountOfParts = ВсеНайденныеФайлы.Количество();
		ОбъектЗапроса.MessageName = "Тестовая отправка сообщения!";
		ОбъектЗапроса.FileExtention = ИсходныйФайл.Расширение;
		ОбъектЗапроса.FileName = ИсходныйФайл.ИмяБезРасширения;
		ОбъектЗапроса.Size = Эл.Размер();
		Результат = Прокси.execute(ОбъектЗапроса);
		
		НомерЧасти = НомерЧасти + 1;
	КонецЦикла;
	
	Попытка
		УдалитьФайлы(ВременныйКаталог, "*");
	Исключение КонецПопытки;
	
	Возврат ИдентификаторСообщения;
	
КонецФункции

Для получения исходного файла из сохраненных в регистре сведении его частей используется следующая функция: 

// Отправляет указанный файл на сервер через веб-сервис
//	Параметры:
//		1. ИдентификаторСообщения - Уникальный идентификатор. Идентификатор, возвращенный функцией "ОтправитьФайл"
//	Возвращаемое значение:
//		Строка. Путь к собранному файлу на сервере
//
Функция ПолучитьФайл(ИдентификаторСообщения) Экспорт
	
	Slash = Символ(92); // Символ "/"
		
	// Создаем временный каталог для записи в него сохраненных ранее в базе частей
	КаталогВременныхФайлов = КаталогВременныхФайлов() +"ReceivingMessageWS";
	ВременныйКаталог = КаталогВременныхФайлов + Slash + ИдентификаторСообщения;
	СоздатьКаталог(ВременныйКаталог);
	ИмяРезультатирующегоФайла = Неопределено;
	
	// Получаем все сохраненные части в базе
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	ПринятыеЧастиПакета.ИдентификаторПакета,
		|	ПринятыеЧастиПакета.НомерЧасти,
		|	ПринятыеЧастиПакета.ДанныеЧастиСообщения,
		|	ПринятыеЧастиПакета.ДатаСоздания,
		|	ПринятыеЧастиПакета.ВсегоЧастей,
		|	ПринятыеЧастиПакета.ИмяСообщения,
		|	ПринятыеЧастиПакета.РасширениеФайла,
		|	ПринятыеЧастиПакета.ИмяФайла,
		|	ПринятыеЧастиПакета.РазмерФайла
		|ИЗ
		|	РегистрСведений.ПринятыеЧастиПакета КАК ПринятыеЧастиПакета
		|ГДЕ
		|	ПринятыеЧастиПакета.ИдентификаторПакета = &ИдентификаторПакета";	
	Запрос.УстановитьПараметр("ИдентификаторПакета", ИдентификаторСообщения);	
	РезультатЗапроса = Запрос.Выполнить();
	Если НЕ РезультатЗапроса.Пустой() Тогда
		Выборка = РезультатЗапроса.Выбрать();
		
		МассивИменФайловДляОбъединения = Новый Массив;

		// Сохраняем файлы частей во временный каталог
		Пока Выборка.Следующий() Цикл
			ИмяЧастиФайла = ВременныйКаталог + Slash + Выборка.ИмяФайла + Выборка.РасширениеФайла + "." + Формат(Выборка.НомерЧасти, "ЧГ=0");
			Выборка.ДанныеЧастиСообщения.Получить().Записать(ИмяЧастиФайла);
			МассивИменФайловДляОбъединения.Добавить(ИмяЧастиФайла);
		КонецЦикла;
		// Собираем исходный файл
		ИмяРезультатирующегоФайла = КаталогВременныхФайлов + Slash + Выборка.ИмяФайла + Выборка.РасширениеФайла;
		ОбъединитьФайлы(МассивИменФайловДляОбъединения, ИмяРезультатирующегоФайла); 
		
		Попытка
			УдалитьФайлы(ВременныйКаталог, "*");
		Исключение КонецПопытки;
		
	КонецЕсли;
	
	Возврат ИмяРезультатирующегоФайла;
	
КонецФункции

Вот и все, такая простая реализация! Посмотрим на результат.

Проверка

Передача файла была продемонстрирована выше, теперь же давайте посмотрим на работоспособность функции получения ранее переданного файла.

Как видим, исходный файл получен с тем же размером. Задача выполнена!

Выводы

При регулярном использовании веб-сервиса для передачи больших по размеру сообщений наиболее предпочтителен второй вариант решения, который позволяет сделать универсальную и надежную передачу сообщений вне зависимости от настроек веб-сервера и исходного размера файла.

Предложенный механизм передачи больших сообщений можно развивать, добавляя проверки корректной отправки сообщений, автоматическую очистку битых пакетов из регистра сведений, очистку устаревших данных из регистра и др. Был показан лишь принцип, остальное дело за Вами!

 

P.S. Оригинал статьи и другие материалы по интеграции через веб-сервисы, использование HTTP-сервисов, создание асинхронных виджетов и многое другое Вы можете найти в моем блоге www.develplatform.ru

веб-сервисы интеграция обмен IIS данными XDTO большие файлы

См. также

Интеграция Альфа Авто 5 / Альфа Авто 6 и AUTOCRM / Инфотек

Сайты и интернет-магазины WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    15748    10    17    

11

Интеграция 1С — Битрикс24. Обмен задачами

Сайты и интернет-магазины Интеграция WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Платные (руб)

Интеграция 1С и Битрикс24. Разработка имеет двухстороннюю синхронизацию 1С и Битрикс24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (8.3.18.1289). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

5040 руб.

04.05.2021    17551    6    15    

13

Интеграция с сервисом vetmanager

WEB-интеграция Платформа 1С v8.3 Бухгалтерский учет 1С:Бухгалтерия 3.0 Бытовые услуги, сервис Платные (руб)

Внешняя обработка разрабатывалась для загрузки документов из Ветменеджер в 1С: Бухгалтерия 3.0

12000 руб.

02.02.2021    16360    42    49    

23

[Расширение] БОР-Навигатор.Культура

Зарплата Бюджетный учет WEB-интеграция Обмен с ГосИС Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры государственного учреждения 3 Государственные, бюджетные структуры Россия Бюджетный учет Платные (руб)

Расширение конфигурации, включающее в себя объекты, необходимые для подготовки и сдачи отчета "Штатная численность" системы "БОР-Навигатор.Культура" в программе "1С:Зарплата и кадры государственного учреждения", редакция 3.1.

8400 руб.

01.02.2019    25741    9    0    

7

Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС

Обмен с ГосИС WEB-интеграция Платформа 1С v8.3 Управляемые формы 1С:Комплексная автоматизация 1.х 1С:Бухгалтерия 2.0 1С:Управление торговлей 10 1С:Управление производственным предприятием 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия государственного учреждения 1С:Документооборот 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Платные (руб)

Обработка является альтернативой механизму, разработанному фирмой 1С и заполняющему реквизиты контрагента по ИНН или наименованию. Не требуется действующей подписки ИТС. Вызывается как внешняя дополнительная обработка, т.е. используется, непосредственно, из карточки контрагента. Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС (egrul.nalog.ru) для БП 2.0, БП 3.0, БГУ 1.0, БГУ 2.0, УТ 10.3, УТ 11.x, КА 1.1, КА 2.x, УПП 1.x, ERP 2.x, УНФ 1.5, УНФ 1.6, УНФ 3.0, ДО 2.1

2400 руб.

28.04.2016    88583    160    215    

318
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. script 128 06.12.15 09:40 Сейчас в теме
Данная методика давно уже используется во многих типовых решения для обмена с мобильным клиентом. Только регистр там называется ОчередиСообщений. Ну нужно сказать что деление файла на части хоть и позволяет передать много данных, но существенно тормозит процесс обмена. Все как всегда, что быстрее работать с одним большим файлом или с кучей мелких.
i.c.h; user1038929; +2 Ответить
2. пользователь 06.12.15 10:11
(1) script, спасибо за информацию. Там это реализовано немного сложнее. Но принцип, согласен, тот же.
3. DitriX 2091 06.12.15 15:25 Сейчас в теме
А еще до мобильной - это есть все в бсп :)
Но есть и другое решение - вам надо с УТП забрать файл в 1Гб, и поместить его, например, в документооборот, не важно.
Действия такие - документооборот подключается к УТП (возможно по инициализации самой УТП) и забирает оттуда файл в 1Гб без ограничений :)
4. пользователь 06.12.15 16:36
(3) DitriX, только не говорите, что он подключается по COM =)
19. ojiojiowka 30.07.20 12:11 Сейчас в теме
(3) извините, но не могли бы подсказать, где такое реализовано в БСП? Сходу не смог найти. Название регистра или имя функции, которая использует такой подход скажите пожалуйста.
5. bonv 1510 07.12.15 11:59 Сейчас в теме
В первую очередь, говоря про передачу больших файлов, следует отметить, что использование SOAP имеет накладные расходы в виде увеличения объема передаваемых данных на 33%.
Лучше использовать голый HTTP.
9. пользователь 07.12.15 22:13
(5) bonv, согласен, можно и JSON использовать, уже будет легче. Совершенству нет предела)
13. Dementor 1015 09.12.15 12:00 Сейчас в теме
(5) bonv, если использовать бинарный тип (hexBinary), то накладные расходы SOAP будут всего лишь в добавлении envelope-обвязки пакета - можно пренебречь. Сам к сожалению не экспериментировал, так как мне были доступны для передачи файлы кодированные в Base64 (как раз эти самые потери 33% на увеличении объема), но если возможность в платформе есть, то и имеется вероятность отличная от нуля, что это работает.

При передаче файлов POST-ом по протоколу HTTP та же петрушка, что и при SOAP - данные часто передают типом application/x-www-form-urlencoded
YPermitin; +1 Ответить
16. пользователь 09.12.15 13:18
(13) Dementor, Вы правы, сам SOAPовский конверт имеет незначительный вес, а вот преобразование в base64 увеличивает размер передаваемых данных на треть.

(14) premier, проще отслеживать состояние передачи пакета, можно запросами платформы получать состояния передачи пакетов и т.д., а с каталогом пришлось бы для этого делать "извраты" с чтением файлов и т.д. Сами данные пакета не обязательно записывать в регистр сведений, можно в нем хранить лишь путь к файлу части пакета на диске (что-то вроде хранения файлов в томах). На рабочей базе лучше реализовать периодическую очистку этого регистра, чтобы старые пакеты в нем не хранились долго.

Вариантов реализации масса)
17. bonv 1510 10.12.15 07:56 Сейчас в теме
(13) срочно учить матчасть!
если использовать бинарный тип (hexBinary), то накладные расходы SOAP будут всего лишь в добавлении envelope-обвязки пакета - можно пренебречь

Если использовать hexBinary, то расходы будут 100%. hexBinary использует для отображения одного байта 2 символа.

А вот MTOM в платформе еще пока нет. Так что только голый HTTP.

При передаче файлов POST-ом по протоколу HTTP та же петрушка, что и при SOAP - данные часто передают типом application/x-www-form-urlencoded

А application/x-www-form-urlencoded то тут причем. Данный формат предназначен для передачи параметров веб-формы. Для передачи бинарных данных никто его в здравом уме использовать не будет.
6. bonv 1510 07.12.15 12:03 Сейчас в теме
(0)
Slash = Символ(92); // Символ "/"
....
ВременныйКаталог = КаталогВременныхФайлов()+"SendingMessageWS"+Slash+ИдентификаторСообщения;

Черт, вы это серьезно? Разделитель задаете через это Символ(92)?
memb3r; vtas; YPermitin; +3 Ответить
8. пользователь 07.12.15 22:12
(6) bonv, Это не то, что вы подумали! =D
7. comol 5051 07.12.15 14:05 Сейчас в теме
Круто! Вопрос только один: А нафига зачем??? Одно дело упростить себе жизнь и использовать SOAP для построения событийной модели обмена... Другое дело лить через http протокол файлы. Ну и выгружайте тогда уж в файл, притом лучше не XML, а хотя бы FI тогда уж... а по SOAP передавайте ссылку на него...
memb3r; YPermitin; skif47; Mick2iS; +4 Ответить
10. пользователь 09.12.15 08:49
(7) comol, сразу забыл ответить, сорри)
Так то оно так, но если переход на обмен через веб-сервисы выполняется со старого транспорта, который выполнял выгрузку в XML, то время на изменение обмена может очень дорого стоить компании. Компромиссный вариант - изменить вид транспорта и немного механизмы обработки сообщений, вместо переписки основной части выгрузки и загрузки данных.
11. skif47 350 09.12.15 08:59 Сейчас в теме
В одной своей разработке тоже уткнулся в относительно большие размеры сообщений, передаваемых через SOAP (в моем случае 7-8 МБ).
Загрузка с тестового сервера Амазон во Франкфурте не прошла: отвалилось по таймауту.
Стал на стороне сервера сжимать ответ сервера в ZIP и передавать его тем же SOAP как base64Binary (http://www.w3.org/2001/XMLSchema). Средний размер файла оказался уже около 500 КБ. Распаковка в XML и парсинг в XDTO объект проблем не вызвала, поскольку сам объект WSProxy предоставляет заодно и фабрику XDTO, которой уже можно парсить разжатые ответы.
Протестировал то же самое со сжатием FastInfoSet вместо XML - выигрыш получился незначительный.
Если вместо SOAP использовать HTTP, тоже будет некоторый выигрыш.

А идеально (в моем случае, по крайней мере) использовать рецепт из (7), причем даже асинхронный. Т.е. сервер сразу же возвращает URL файла. А клиент периодически проверяет наличие этого файла, и, как только тот стал доступен, начинает скачивать. Возможно, уже с разбивкой на пакеты.

В любом случае за тему плюс ))
12. Dementor 1015 09.12.15 11:35 Сейчас в теме
Идея интересная, если делать тиражное решение для абстрактного клиента, на инфраструктуру которого не возможно повлиять.
Но на своем опыте могу сказать - при задаче частого обмена большими файлами проще в веб-сервере убрать ограничение для опубликованной базы.
15. пользователь 09.12.15 13:10
(12) Dementor, админы негодуют, когда просишь убрать ограничения. В принципе я с ними согласен)
14. premierex 204 09.12.15 12:37 Сейчас в теме
(0) А я вот не понял смысла промежуточной записи файлов в регистр сведений. Почему сразу в каталог с неким GUID их не писать, а имена коротких файлов для дальнейшего объединения запоминать в массиве?
18. rail21111991 30.12.15 13:54 Сейчас в теме
Оставьте свое сообщение