Недавно пришлось добавить авторизацию в сервисе, который принимает данные в виде form-data. Попробовал найти какую-то инструкцию, но ничего связного, в одном месте, не нашел. Так что, как обычно, записываю шпаргалку. Как из 1С отправить Post запрос с данными в формате multipart/form-data, или «данные формы».
Последовательность действий такая:
- сгенерировать код который будет использоваться как граница блоков данных, boundary; разделитель будет состоять из двух тире, префикса и этого кода
- данные — пары ключ-значение, записать в тело, разделяя строками с разделителем, внутри блока данных записывается имя данных и, через пустую строку, значение
- последний разделитель записать с добавлением двух тире в конце
- посчитать размер тела и сформировать заголовки, в заголовке нужно указать код, сгенерированный на первом шаге
- отправить запрос
Теперь то же самое, в виде кода:
Function PostFormData(Conn, Path, Data, StatusCode=0, Err=Undefined) Export
Err = Undefined;
StatusCode = 0;
If TypeOf(Data) <> Type("Structure") Then
Err = "Unsupported form data for POST request";
Return "";
EndIf;
Boundary = "Boundary" + StrReplace(String(New UUID()), "-", "");
Splitter = "--" + Boundary;
Body = New MemoryStream();
Writer = New DataWriter(Body);
For Each Param In Data Do
Writer.WriteLine(Splitter);
Writer.WriteLine("Content-Disposition: form-data; name=""" + Param.Key + """");
Writer.WriteLine("");
Writer.WriteLine(Param.Value);
EndDo;
Writer.WriteLine("" + Splitter + "--");
Writer.Close();
Size = Format(Body.Size(), "NG=0");
BinaryData = Body.CloseAndGetBinaryData();
Headers = New Map;
Headers.Insert("Content-Type", "multipart/form-data; boundary=" + Boundary);
Headers.Insert("Content-Length", Size);
Req = New HTTPRequest(Path, Headers);
Req.SetBodyFromBinaryData(BinaryData);
Try
Resp = Conn.POST(Req);
Except
Err = ""+Path+": "+BriefErrorDescription(ErrorInfo());
Return "";
EndTry;
StatusCode = Resp.StatusCode;
Return Resp.GetBodyAsString();
EndFunction // PostFormData()
Функция принимает объект HTTPСоединение, путь и данные в виде структуры. Переменные StatusCode и Err нужны чтобы вернуть статус ответа и ошибку если что то пошло не так. Генерируется код на основании которого составляется разделитель Splitter, затем, с помощью объекта MemoryStream (ПотокВПамяти) записывается тело запроса.
В 1С 7.7 такого простого способа нет. Когда мне это было нужно, я добавил отправку мультипарт данных через вспомогательное внешнее приложение (ссылка).