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

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

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

В наличии

Потребовалось отправить картинку в теле запроса в 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Запрос); // финал

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

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