Каталог решений - REST API multipart/form-data или отправка файлов в nexus

REST API multipart/form-data или отправка файлов в nexus

REST API multipart/form-data или отправка файлов в nexus

В наличии

Понадобилось в nexus складывать файлы для автодеплоя. Для этого использовал onescript и rest api.
Библиотека 1connector не отработала, примеры на зазеркалье и ИТС тоже. В этой статье расскажу как поборол проблему.

Категория:

Описание

По REST API много документации и проблем при работе с ним не ожидалось.
Но при попытке отправить в нексус файл получал ошибки.
Пробовал компоненту "1connector",
статьи
https://its.1c.ru/db/metod8dev/content/5917/hdoc
https://wonderland.v8.1c.ru/blog/novye-instrumenty-dlya-raboty-s-dvoichnymi-dannymi-obespechivayut-kak-posledovatelnyy-dostup-k-danny/
и поисковики.

Вики дает неполное описание формата https://ru.wikipedia.org/wiki/Multipart/form-data.
Добирал описание на разных ресурсах.

Требования к формату "multipart/form-data"

1. определить нужные заголовки запроса
2. правильно описать тело запроса

Заголовки запроса

Сначала идет разделитель состоящий из букв и цифр.
Потом длина тела сообщения.

Пример:

ТипКонтента = СтрШаблон("multipart/form-data; boundary=%1", Разделитель); 
HTTPЗапрос.Заголовки.Вставить("Content-Type", ТипКонтента);
HTTPЗапрос.Заголовки.Вставить("Content-length", РазмерСодержимого);

Описание тела запроса

Сначала открывается сообщение "—Разделитель"
Потом описываются переменные и их значения
При необходимости добавить другие переменные указываем еще один разделитель и описываем их.
Для закрытия сообщения указываем "—Разделитель—"
Обращаем внимание: для закрытия сообщения после разделителя указывается "—".

Пример:

—Разделитель
Content-Disposition: form-data; name=""Имя переменной"""
Пустая строка
Значение переменной
—Разделитель
Content-Disposition: form-data; name=""Имя переменной"""
Пустая строка
Значение переменной
—Разделитель—
 

Как проверить

Для проверки корректного разделения можно посмотреть в фидлере как отработало разделение.

 

Образец кода

Работает как в OneScript версии 1.2 и выше так и в 1С 8.3.14
На вход подается адрес репозитория, полный путь к файлу.
Код не полный и предоставляется для ознакомления только отправка.

Процедура ОтправитьФайлВНексус(АдресРепозитория, ПолноеИмяФайла)
	
	Отладка = Истина;
	
	Если Отладка Тогда
		Сообщить("ПолноеИмяФайла " + ПолноеИмяФайла);
	КонецЕсли;
	
	СтруктураURI = СтруктураURI(АдресРепозитория);
	
	Логин = "---";
	Пароль = "---";
	
	Соединение = Новый HTTPСоединение(СтруктураURI.Хост, , Логин, Пароль, , 1200);
	
	ЗаголовокЗапросаHTTP = Новый Соответствие();
	ЗаголовокЗапросаHTTP.Вставить("User-Agent", "1C+Enterprise/8.3");
	
	ЗапросHTTP = Новый HTTPЗапрос(СтруктураURI.ПутьНаСервере, ЗаголовокЗапросаHTTP);
	ЗакодироватьФайлы(ЗапросHTTP, ПолноеИмяФайла);
	
	Ответ = Соединение.ВызватьHTTPМетод("POST", ЗапросHTTP);
	СообщениеОтвет = Ответ.ПолучитьТелоКакСтроку();
	
	ОписаниеОтвета = "" + Ответ.КодСостояния + " " + СообщениеОтвет;
	
	Если НЕ (Ответ.КодСостояния = 200 или Ответ.КодСостояния = 204) Тогда
		ВызватьИсключение ОписаниеОтвета;
	КонецЕсли;

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

Процедура ЗакодироватьФайлы(HTTPЗапрос, ПолноеИмяФайла)

	Разделитель = СтрЗаменить(Новый УникальныйИдентификатор, "-", "");
	РазделительСтрок = Символы.ВК + Символы.ПС;
	
	Файл = Новый Файл(ПолноеИмяФайла);
	Если НЕ Файл.Существует() Тогда
		ВызватьИсключение "Не найден файл " + ПолноеИмяФайла + " для отправки в нексус";
	КонецЕсли;
	РазмерФайла = Файл.Размер();
	
	БуферДвоичныхДанных = Новый БуферДвоичныхДанных(РазмерФайла);
	
	ФайловыйПоток = Новый ФайловыйПоток(Файл.ПолноеИмя, РежимОткрытияФайла.Открыть);
	ФайловыйПоток.Прочитать(БуферДвоичныхДанных, 0, РазмерФайла);
	ФайловыйПоток.Закрыть();
	
	ПотокТело = Новый ПотокВПамяти();
	ЗаписьДанных = Новый ЗаписьДанных(ПотокТело);
	
	ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель);
	ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""raw.directory""");
	ЗаписьДанных.ЗаписатьСтроку("");
	ЗаписьДанных.ЗаписатьСтроку("oneclog");
	ЗаписьДанных.ЗаписатьСтроку("");
	
	ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель);
	ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""raw.asset1.filename""");
	ЗаписьДанных.ЗаписатьСтроку("");
	ЗаписьДанных.ЗаписатьСтроку(Файл.ИмяБезРасширения + Файл.Расширение);
	ЗаписьДанных.ЗаписатьСтроку("");
	
	ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель);
	ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/x-executable");
	ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""raw.asset1""");
	ЗаписьДанных.ЗаписатьСтроку("");
	ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(БуферДвоичныхДанных);
	ЗаписьДанных.ЗаписатьСтроку("");
	
	ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель + "--");
	
	РазмерСодержимого = XMLСтрока(ПотокТело.Размер());
	ЗаписьДанных.Закрыть();
	
	ДвоичныеДанныеТело = ПотокТело.ЗакрытьИПолучитьДвоичныеДанные();
	
	HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеТело);
	
	ТипКонтента = СтрШаблон("multipart/form-data; boundary=%1", Разделитель);
	
	HTTPЗапрос.Заголовки.Вставить("Content-Type", ТипКонтента);
	HTTPЗапрос.Заголовки.Вставить("Content-length", РазмерСодержимого);
	
КонецПроцедуры

 

has been added to your cart:
Оформление заказа