Воспроизвести WS — post multipart /form-данные из scala — неверный запрос

#scala #playframework #multipartform-data

#scala #playframework #составная часть-данные

Вопрос:

Я пытаюсь отправить PDF-файл во внешнюю службу с помощью запроса multipart / form-data. Я сделал это с образцом клиента Java Script, чтобы внешняя служба работала должным образом. Я перешел в scala со следующим кодом, который я получил: Неверный запрос:

 import akka.stream.scaladsl.FileIO
import akka.stream.scaladsl.Source
import play.api.libs.ws.WSClient
import play.api.mvc.MultipartFormData._

val pathToFile = "./sampleCV.pdf"
val fileName = "sampleCV.pdf"
val futureResponse = ws.url(url).withRequestTimeout(Duration.create(55, TimeUnit.SECONDS))
      .addHttpHeaders("authorization" -> s"bearer $access_token")
      .addHttpHeaders("accept" -> "*/*")
      .addHttpHeaders("content-type" -> "multipart/form-data")
      .post(Source(
        FilePart("File", fileName, Option("application/pdf"), FileIO.fromPath(Paths.get(pathToFile)))  :: List()
      ))
  

Версия воспроизведения: 2.6.19

Следуя команде curl, загрузите файл правильно:

curl -X POST "https://rest_url" -H "accept: */*" -H "Authorization: bearer <TOKEN>" -H "Content-Type: multipart/form-data" -F "File=@sampleCV.pdf;type=application/pdf"

Я пропустил какой-то важный параметр в post(...) ? Каковы соответствующие параметры post в ScalaWS, которые соответствуют этому запросу CURL?

Комментарии:

1. Сначала проверьте свой запрос, например, с помощью cURL

2. Я отредактировал вопрос и добавил пример curl POST, который работает с этим сервисом. Спасибо!

3. Заголовок accept отличается, также поле файла File != cv и проверьте токен (который в качестве значения Scala должен быть скорее назван accessToken )

4. Выполнено — результат тот же — Неверный запрос

Ответ №1:

При использовании составных / данных формы требуется параметр границы. Заголовок типа содержимого будет выглядеть примерно так:

 Content-Type: multipart/form-data; boundary=nZaYg9TFHoDaLWhs8w
  

Вы задаете заголовок типа содержимого с помощью addHttpHeaders , но поскольку в нем отсутствует параметр boundary, он не работает.
Решение состоит в том, чтобы не устанавливать этот заголовок вручную, фактически вам никогда не понадобится устанавливать этот заголовок. Play-WS добавит соответствующий заголовок типа содержимого на основе типа объекта, который вы передаете post методу. Когда вы передаете Source[Part[Source[ByteString, Any]]] , он установит тип содержимого составных / данных формы, а также добавит соответствующий граничный параметр.

Ответ №2:

Я столкнулся с той же проблемой, добавив заголовок Content-Length, решаемый в mycase. Добавлен заголовок, как показано ниже, в WSRequest,

 wsRequest.setHeader("Content-Length", String.valueOf(fileToUpload.length()));
  

Здесь fileToUpload является java.io .Файловый объект, который вы пытаетесь загрузить.