3

I am trying to post pdf file to external service with multipart/form-data request. I've done this with sample Java Script client so the external service works properly. Hovewer in scala with the following code I got: Bad request:

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()
      ))

Play version: 2.6.19

Following curl command upload the file properly:

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"

Did I miss some important parameter in post(...) ? What are appropriate post parameters in ScalaWS which corresponds to this CURL request?

2 Answers2

2

When multipart/form-data is used, a boundary parameter is required. The Content-Type header is going to look something like this:

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

You set the Content-Type header using addHttpHeaders, but since it lacks the boundary parameter, it doesn't work. The solution is to not set that header manually, in fact you should never need to set that header. Play-WS will add an appropriate Content-Type header based on the type of object that you pass to the post method. When you pass a Source[Part[Source[ByteString, Any]]], it will set the multipart/form-data Content-Type and also add an appropriate boundary parameter.

Matthias Berndt
  • 4,387
  • 1
  • 11
  • 25
0

I faced the same issue, adding Content-Length header solved in mycase. Added header as below to WSRequest,

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

Here fileToUpload is java.io.File object which you are trying to upload.