Обмен с HTTP сервисом файлами по формату multipart/form-data

07.09.21

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

Потребовалось отправить картинку в теле запроса в HTTP сервис методом POST, куча реализаций, но есть маленькие нюансы, если хотя бы кому-то поможет, то уже это было не напрасно.

Все как всегда, легко и просто

Создаем соединение через Новый HTTPСоединение()

Создаем HTTPЗапрос через Новый HTTPЗапрос()

Дальше все кажется логичным и простым

Методом HTTP запроса УстановитьТелоИзДвоичныхДанных() передаем в него картинку и отправляем

Было бы очень легко и интуитивно понятно, но тут начинается веселье, как по мне

Формат multipart/form-data требует очень четкой структуры данных

Через Postman смотрим snippet

// ЗАГОЛОВКИ

Content-Length: 232 // длина сообщения, не обязательна
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW // определение типа данных и указание разделителя

// Тело запроса
----WebKitFormBoundary7MA4YWxkTrZu0gW // разделитель
Content-Disposition: form-data; name="file"; filename="Scan.jpg" // описание поля по формату с указанием имени поля "file" и название данных для принимающей стороны
Content-Type: image/jpeg // тип данных

(data) // сами данные
----WebKitFormBoundary7MA4YWxkTrZu0gW // закрывающий  разделитель

Тоже все понятно и легко вроде как, но я словил так называемую ошибку, над которой даже не задумался

1. Структура должна быть обязательно именно такой, повторяя каждый отступ и перенос

Разделитель, Символ.ВК, Символ.ПС
Описание, Символ.ВК, Символ.ПС
ОписаниеТипа, Символ.ВК, Символ.ПС,
Символ.ВК, Символ.ПС
ДвочныеДанные, Символ.ВК, Вимвол.ПС
Разделитель

2. При записи через поток при определении ЗаписьДанных можно переопределить

РазделительСтрок - Значение по умолчанию: ПС
КонвертируемыйРазделительСтрок - Значение по умолчанию: ВК + ПС

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

В итоге код, который отработал, в конечном варианте выглядит вот так: 


КартинкаИмяПараметра = "file";
КартинкаИмяФайла = "Scan.jpg";
Картинка = Новый Картинка(АдресФайла); // любым удобным способом, по факту нужны ДД изображения
// 
Разделитель = СтрЗаменить(Новый УникальныйИдентификатор(), "-", ""); // все что угодно, можно даже руками указать "razzdell", главное что бы оно было уникальное во всем тексте тела

// --Отладочный кусок
// ИмяВременногоФайла = ПолучитьИмяВременногоФайла("txt"); // временный файл для сохранения полученного тела для запроса
// ++Отладочный кусок

Тело = Новый ПотокВПамяти();
ЗаписьДанных = Новый ЗаписьДанных(Тело, , , Символы.ВК + Символы.ПС, ""); // то самое переопределение разделителей               
ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=" + КартинкаИмяПараметра + "; filename=" + КартинкаИмяФайла);
ЗаписьДанных.ЗаписатьСтроку("Content-Type: image/jpeg");
ЗаписьДанных.ЗаписатьСтроку(""); // пустая строка для доп переноса и воспроизведения структуры тела
ЗаписьДанных.Записать(Картинка.ПолучитьДвоичныеДанные()); // добавляет данные но каретка остается после данных
ЗаписьДанных.ЗаписатьСтроку(""); // записать не добавляет переносов, добавляем их пустой строкой
ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель + "--"); // добавляются еще доп переносы, но они уже не на что не влияют, так же после разделителя добавляем "--", должно обозначать конец тела
ЗаписьДанных.Закрыть();

ДанныеТела = Тело.ЗакрытьИПолучитьДвоичныеДанные(); // получаем дело в дд, можно и через запись в файл, просто лишний раз не трогаем диски и не делаем доп операций

// --Отладочный кусок
//	ДанныеТела.Записать(ИмяВременногоФайла); // записывает ДД в txt файл
// ++Отладочный кусок

HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ДанныеТела); // установили тело
HTTPЗапрос.Заголовки.Вставить("Content-Length", XMLСтрока(ДанныеТела.Размер()));
HTTPЗапрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + разделитель);
ОтветHTTP = Соединение.ОтправитьДляОбработки(HTTPЗапрос); // финал


Если есть возможность улучшить, адаптировать, сделать проще, я только за, жду в комментариях.

Обен POST HTTP Картинка УстановитьТелоИзДвоичныхДанных Поток

См. также

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

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

57600 руб.

26.11.2024    1535    1    1    

4

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

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

36000 руб.

03.08.2020    18565    20    22    

18

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

Интеграция 1С и Битрикс 24. Разработка имеет двухстороннюю синхронизацию 1С и Bitrix24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (платформа начиная с 8.3.23): 1С:Управление торговлей, 1С:Управление Нашей фирмой 3, 1С:Комплексная автоматизация 2, Объединенное решение: Модуль 1С:CRM 3 (3.0.21.3) +1С:ERP Управление предприятием 2. При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

7200 руб.

04.05.2021    20710    13    19    

18

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

Модуль "Экспортер" — это расширение для 1С, предназначенное для автоматизации процессов выгрузки данных. Оно позволяет эффективно извлекать, преобразовывать и передавать данные из систем 1С в интеграционную платформу Spot2D. Подсистема упрощает настройку, снижает количество ручных операций и обеспечивает удобный контроль данных.

14400 руб.

20.12.2024    474    2    0    

5

Обмен с ГосИС 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    92184    184    217    

337
Отзывы
24. userfirerain 16.01.22 21:39 Сейчас в теме
Блестяще, что все названия переведены на русский! Только учитывая, что такой язык мало где применяется, и почти всегда приходится пока что писать на английском, нельзя ли было в скобках продублировать, как это в стандартной английской Яве звучит? Не всегда легко на лету переводить обратно.
Остальные комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. frkbvfnjh 808 07.09.21 14:44 Сейчас в теме
Как раз искал простой пример кода для отправки запроса в формате multipart/form-data. Спасибо!
sikuda; Serg O.; +2 Ответить
23. igorprokopjuk 05.12.21 16:54 Сейчас в теме
Спасибо за статью, Ваш метод рабочий, мне тоже помогло !
2. frkbvfnjh 808 07.09.21 14:59 Сейчас в теме
4. ix5s 134 07.09.21 15:11 Сейчас в теме
(2) Спасибо
По факту лишние для прода

ИмяВременногоФайла = ПолучитьИмяВременногоФайла("txt"); // временный файл для сохранения полученного тела для запроса

Там еще должна была быть строка записи все в txt, сейчас добавлю

ДанныеТела.Записать(ИмяВременногоФайла);
igorprokopjuk; +1 Ответить
3. frkbvfnjh 808 07.09.21 15:03 Сейчас в теме
А можете для наглядности еще привести пример запроса когда нужно отправить например несколько файлов/картинок. В таком случае не совсем понятно как расставить разделители. А еще лучше как слать в перемешку текст с двоичными данными.
5. ix5s 134 07.09.21 15:13 Сейчас в теме
(3)Если есть пример сервиса куда можно закидывать несколько файлов, картинок, можно было бы попробовать расширить, но по факту блок универсален, повторяем все тоже самое без закрывающего разделителя, закрывающий один в самом конце
6. frkbvfnjh 808 07.09.21 15:18 Сейчас в теме
7. Sodrugestvo 07.09.21 18:56 Сейчас в теме
Посмотрите реализацию в библиотеке коннектор
https://github.com/vbondarevsky/Connector
к вопросу улучшить и адаптировать
triviumfan; JohnyDeath; CSiER; +3 Ответить
9. ix5s 134 07.09.21 23:13 Сейчас в теме
(7)спасибо, видел, изучаю, восхищаюсь)
8. пользователь 07.09.21 20:59
Сообщение было скрыто модератором.
...
10. malikov_pro 1327 08.09.21 04:14 Сейчас в теме
"Content-Length: 232 // длина сообщения, не обязательна" - при установке тела через строку некорректно считало длину (8.3.17) из за чего сторонний сервис не мог прочитать данные

HTTPЗапрос.Заголовки.Вставить("Content-Length", XMLСтрока(ДанныеТела.Размер()));
11. ix5s 134 08.09.21 08:46 Сейчас в теме
(10)Спасибо, добавлю в статью если не против, вроде тоже на 8.3.17, скорее всего дело в стороннем сервисе
12. Поручик 4661 08.09.21 09:50 Сейчас в теме
Еще в 2018 году делал передачу файла через тело запроса.
13. Поручик 4661 08.09.21 09:58 Сейчас в теме
Собственно, принцип тот же самый.
		ПотокТело = Новый ПотокВПамяти();
		ЗаписьДанных = Новый ЗаписьДанных(ПотокТело);
		
		ЗаписьДанных.ЗаписатьСтроку("--" + Boundary);
		ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""resumableType""");
		ЗаписьДанных.ЗаписатьСтроку("");
		ЗаписьДанных.ЗаписатьСтроку("application/" + ДанныеФайла.Расширение);
		
		ЗаписьДанных.ЗаписатьСтроку("--" + Boundary);
		ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""" + ИмяФайлаДляЗагрузки + """");
 		ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/x-octet-stream");
		ЗаписьДанных.ЗаписатьСтроку("");
		ЗаписьДанных.Записать(МассивЧастей[НомерЧасти - 1].ПолучитьДвоичныеДанные());
		ЗаписьДанных.ЗаписатьСтроку("");
		
		ЗаписьДанных.ЗаписатьСтроку("--" + Boundary + "--");
		
		ЗаписьДанных.Закрыть();
		ДвоичныеДанныеТело = ПотокТело.ЗакрытьИПолучитьДвоичныеДанные();
		
		ЗаголовкиHTTP = Новый Соответствие;
		ЗаголовкиHTTP.Вставить("Accept", "*/*");
		ЗаголовкиHTTP.Вставить("Content-Type", "multipart/form-data; boundary=" + Boundary);
		ЗаголовкиHTTP.Вставить("Content-Length", XMLСтрока(ДвоичныеДанныеТело.Размер()));
Показать

Дальше штатный способ
magv; Il; Yashazz; +3 Ответить
15. ix5s 134 08.09.21 12:28 Сейчас в теме
(13)Да все один в один, не видел вашего кода, на сайте ИТС есть статья как отправлять данные, составные, текст, файл, картинка. Я больше хотел показать по структуре самого тела, что служебные символы очень сильно влияют (на чем собственно и застрял, с ответом 400 от сервиса) и о том что через постман можно получить структуру и ее 1 в 1 надо повторить в 1С, возможно с отладочным кодом когда тело в txt и глазами просматривать каждый символ
16. triviumfan 98 13.09.21 09:27 Сейчас в теме
(13)
Content-Length
Разве ты его верно рассчитал?)
17. Поручик 4661 13.09.21 09:30 Сейчас в теме
(16) Это кусок кода из успешно работающей года два фичи. Данные передаются в один госконторский сервис.
Значит, верно.
18. triviumfan 98 13.09.21 09:50 Сейчас в теме
(17)
Это кусок кода из успешно работающей года два фичи. Данные передаются в один госконторский сервис.
Значит, верно

Ничего не значит. http-отладчиком проверял?
14. malikov_pro 1327 08.09.21 11:15 Сейчас в теме
(13) Она в комменте была, на сколько помню, использовал в своих проектах, здесь в виде статьи оформлено.
19. Aleskey_K 35 14.09.21 21:08 Сейчас в теме
20. SpaceOfMyHead 197 15.09.21 23:23 Сейчас в теме
Тоже реализовал через поток в памяти. Статья.
21. broo 6 17.09.21 17:00 Сейчас в теме
Спасибо за статью - очень выручило!
22. Global__IT 342 23.09.21 22:13 Сейчас в теме
Интересно. А я через временные файлы реализовывал. Эта библиотеку пользую уже наверное лет 7. Попробую через ПотокВПамяти
24. userfirerain 16.01.22 21:39 Сейчас в теме
Блестяще, что все названия переведены на русский! Только учитывая, что такой язык мало где применяется, и почти всегда приходится пока что писать на английском, нельзя ли было в скобках продублировать, как это в стандартной английской Яве звучит? Не всегда легко на лету переводить обратно.
25. userfirerain 16.01.22 22:17 Сейчас в теме
(24) блин, я же искал по Яве решения, только после регистрации обнаружил, что это по 1С )
Хотел удалить пост, но обнаружил, что можно его только изменить - хотел изменить, но было написано, что редактировать можно только через 30 минут - как дурак, ждал, пока пройдёт 30 минут - теперь внезапно написано наоборот: редактировать можно только 30 минут, а потом нельзя)
AlisultanovZakir; kild; CratosX; Трактор; +4 Ответить
26. ix5s 134 24.01.22 17:40 Сейчас в теме
Оказывается не так то и мало где применяется русский. В нашем мире английский редкость. =)
alexvbard; tosha_n; +2 Ответить
Оставьте свое сообщение