How can I send multi part form data in post method in play scala using : scalaVersion:2.11.7 playVersion-2.1.5
-
Have you had a look at the documentation https://www.playframework.com/documentation/2.1.x/ScalaFileUpload? – Kris Sep 22 '15 at 11:58
-
yes I have seen this documentation this is for file upload I want to send some other fields as form data in post ,I am able to send data in json form but in form- data I don't know how to send in post – Kanchan Sep 22 '15 at 16:02
2 Answers
You need to do a little code, then you can use it like
val data = MultipartFormData(formFields, "asdasboundarystringas")
WS.url(myUrl).post(data.body)
The code of MultipartFormData you can find on the github: https://gist.github.com/EECOLOR/7649144
UPDATE
Another method, I have been try it with Play 2.4.3
package controllers
import play.api.Play.current
import play.api.libs.ws._
import play.api._
import play.api.mvc._
import com.ning.http.client.AsyncHttpClient
import com.ning.http.client.multipart.FilePart
import com.ning.http.client.multipart.StringPart
import java.io.File
class Application extends Controller {
def index = Action {
val url = "http://symlink.dk/code/php/submit/"
val asyncHttpClient:AsyncHttpClient = WS.client.underlying
val postBuilder = asyncHttpClient.preparePost("http://symlink.dk/code/php/submit/")
val builder = postBuilder.addBodyPart(new StringPart("myField", "abc", "UTF-8"))
.addBodyPart(new StringPart("myField1", "abc1", "UTF-8"))
.addBodyPart(new StringPart("myField2", "abc2", "UTF-8"))
.addBodyPart(new FilePart("myFile", new File("app/controllers/Application.scala")))
val response = asyncHttpClient.executeRequest(builder.build()).get();
Ok(response.getResponseBody)
}
}
Symlink does not verify file part, so I am not sure about it, but fileds definitely was send
UPDATE
With Authentication and file verification
package controllers
import play.api.Play.current
import play.api.libs.ws._
import play.api._
import play.api.mvc._
import com.ning.http.client.AsyncHttpClient
import com.ning.http.client.multipart.FilePart
import com.ning.http.client.multipart.StringPart
import java.io.File
import org.apache.commons.codec.binary.Base64.encodeBase64
class Application extends Controller {
def index = Action {
val url = "http://httpbin.org/post"
val name = "MyUserName"
val password = "MyPassword"
val encodedCredentials =
new String(encodeBase64("%s:%s".format(name, password).getBytes))
val asyncHttpClient:AsyncHttpClient = WS.client.underlying
val postBuilder = asyncHttpClient.preparePost(url)
val builder = postBuilder
.addHeader("Authorization", "Basic " + encodedCredentials)
.addBodyPart(new StringPart("myField", "abc", "UTF-8"))
.addBodyPart(new StringPart("myField1", "abc1", "UTF-8"))
.addBodyPart(new StringPart("myField2", "abc2", "UTF-8"))
.addBodyPart(new FilePart("myFile", new File("app/controllers/Application.scala")))
val response = asyncHttpClient.executeRequest(builder.build()).get();
Ok(response.getResponseBody)
}
}
Echo of posted data:
{
"args": {},
"data": "",
"files": {
"myFile": "package controllers\n\nimport play.api.Play.current\nimport play.api.libs.ws._\nimport play.api._\nimport play.api.mvc._\nimport com.ning.http.client.AsyncHttpClient\nimport com.ning.http.client.multipart.FilePart\nimport com.ning.http.client.multipart.StringPart\nimport java.io.File\nimport org.apache.commons.codec.binary.Base64.encodeBase64\n\nclass Application extends Controller {\n\n def index = Action {\n// val url = \"http://symlink.dk/code/php/submit/\"\n val url = \"http://httpbin.org/post\"\n\n val name = \"MyUserName\"\n val password = \"MyPassword\"\n\n val encodedCredentials =\n new String(encodeBase64(\"%s:%s\".format(name, password).getBytes))\n\n val asyncHttpClient:AsyncHttpClient = WS.client.underlying\n val postBuilder = asyncHttpClient.preparePost(url)\n val builder = postBuilder\n .addHeader(\"Authorization\", \"Basic \" + encodedCredentials)\n .addBodyPart(new StringPart(\"myField\", \"abc\", \"UTF-8\"))\n .addBodyPart(new StringPart(\"myField1\", \"abc1\", \"UTF-8\"))\n .addBodyPart(new StringPart(\"myField2\", \"abc2\", \"UTF-8\"))\n .addBodyPart(new FilePart(\"myFile\", new File(\"app/controllers/Application.scala\")))\n val response = asyncHttpClient.executeRequest(builder.build()).get();\n Ok(response.getResponseBody)\n }\n\n}\n"
},
"form": {
"myField": "abc",
"myField1": "abc1",
"myField2": "abc2"
},
"headers": {
"Accept": "*/*",
"Authorization": "Basic TXlVc2VyTmFtZTpNeVBhc3N3b3Jk",
"Content-Length": "1991",
"Content-Type": "multipart/form-data; boundary=ZUeOacX0k9AyI7O12kXDuV5gucDyh2IcA",
"Host": "httpbin.org",
"User-Agent": "AHC/1.0"
},
"json": null,
"origin": "111.111.111.11",
"url": "http://httpbin.org/post"
}
UPDATE
just for clarification - if you do not need to send file as part of the form then you do not need to access underlying WSClient and can use trivial WS
val url = "http://httpbin.org/post"
val name = "MyUserName"
val password = "MyPassword"
val result = WS.url(url)
.withAuth(name, password, WSAuthScheme.BASIC)
.post(
Map(
"myField" -> Seq("myValue"),
"myField1" -> Seq("myValue1"),
"myField2" -> Seq("myValue2")
)
)
val response = Await.result(result, 10 seconds)
Ok(response.body)
request that this code send:
{
"args": {},
"data": "",
"files": {},
"form": {
"myField": "myValue",
"myField1": "myValue1",
"myField2": "myValue2"
},
"headers": {
"Accept": "*/*",
"Authorization": "Basic TXlVc2VyTmFtZTpNeVBhc3N3b3Jk",
"Content-Length": "51",
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
"Host": "httpbin.org",
"User-Agent": "AHC/1.0"
},
"json": null,
"origin": "111.111.111.11",
"url": "http://httpbin.org/post"
}

- 8,093
- 2
- 29
- 46
-
Thanks for your answer :-) but can u give me one template code and one controller class code – Kanchan Sep 22 '15 at 16:04
-
I can tell you my exactly requirements is this I have four fields: file which is I am taking from form and other three fields are static I want to send all these four field as form data in post url ws.url(myurl).post(data) but here data how I can send in mutli part form data in post what I need to give in this data can u tell me – Kanchan Sep 22 '15 at 16:14
-
these two links I am using for solving my problem But this code is not working for me it is giving error type mismatch; found : com.ning.http.client.FluentCaseInsensitiveStringsMap required: com.ning.http.client.FluentStringsMap – Kanchan Sep 22 '15 at 19:07
-
well, it looks like they add support of multipart to the play a year ago: https://groups.google.com/forum/#!msg/play-framework/MPtQlX-cWMQ/rdabLhGwytcJ mb it will help you – Andriy Kuba Sep 22 '15 at 19:22
-
look on the update part - I did verification on my own project. Could you try it on 2.1.5 ? Or mb you would like to migrate on 2.4 :) – Andriy Kuba Sep 22 '15 at 19:52
-
hey in your update part how will I add authentication for particular url – Kanchan Sep 23 '15 at 09:38
-
I suppose you are talking about basic authorization. This post could help you http://stackoverflow.com/questions/17380731/get-url-content-with-basic-authentication-with-java-and-async-http-client I could look later in details how to translate this java to scala if you hard with this – Andriy Kuba Sep 23 '15 at 09:56
-
thanks but in your update part code can u tell me where I need to add authentications details – Kanchan Sep 23 '15 at 10:36
-
with play 2.1.5 it s not working when I am adding this com.ning.http.client.AsyncHttpClient related jar to build.scala then play is unable to get data – Kanchan Sep 23 '15 at 18:48
-
when I am using play 2.4.3 and jdk 1.7 it is telling java.lang.UnsupportedClassVersionError:com/typesafe/config/ConfigExceptionsupported major.minor version 52.0 unable to load project – Kanchan Sep 23 '15 at 19:16
-
It's because ply 2.4 requires JDK 8. You can not run it's on jdk 1.7 sorry :( – Andriy Kuba Sep 23 '15 at 20:57
-
when I am using jdk 1.8 then other problem is coming I tried with 1.8 also – Kanchan Sep 24 '15 at 09:07
-
I am unable to create war file in 2.1.5 that's why I switched to play 2.4.3 in ubuntu and now this same code is not working it is telling 400 bad request can u please tell me what is wrong I am doing. – Kanchan Oct 06 '15 at 07:08
-
I verify it on the 2.4.3 (I am on mac) - it works. Can you create another question with the exactly code you use? – Andriy Kuba Oct 06 '15 at 07:27
-
http://stackoverflow.com/questions/32965746/error-in-sending-data-as-multi-form-data-in-play-scala I posted here can U tell me what I am missing – Kanchan Oct 06 '15 at 08:59
-
hey an u reply for this question given link below http://stackoverflow.com/questions/33200986/how-to-send-forms-element-data-in-controller-classin-play-scala – Kanchan Oct 21 '15 at 09:24
Thanks Andriy Kuba!
I've made some changes (WS.client.underlying didn't work for me) I m running with play 2.4.
package utils
import com.ning.http.client.{AsyncHttpClient, ListenableFuture, Request, Response}
import com.ning.http.client.cookie.Cookie
import com.ning.http.client.multipart.{FilePart, StringPart}
/**
* Created by ozma on 27/05/16.
*/
object WsExtend {
def postFile(url: String,
files: List[(String, String)] = List(),
bodyParams: List[(String, String)] = List(),
cookies: List[Cookie] = List(),
headers: Map[String, String] = Map(),
encoding: String = "UTF-8"): Response = {
postFileAsync(url, files, bodyParams, cookies, headers, encoding).get()
}
def postFileAsync(url: String,
files: List[(String, String)] = List(),
bodyParams: List[(String, String)] = List(),
cookies: List[Cookie] = List(),
headers: Map[String, String] = Map(),
encoding: String = "UTF-8"): ListenableFuture[Response] = {
val asyncHttpClient:AsyncHttpClient = new AsyncHttpClient()
val postBuilder: AsyncHttpClient#BoundRequestBuilder = asyncHttpClient.preparePost(url)
files.foreach(e => postBuilder.addBodyPart(new FilePart(e._1, new java.io.File(e._2))))
bodyParams.foreach(e => postBuilder.addBodyPart(new StringPart(e._1, e._2, encoding)))
cookies.foreach(c => postBuilder.addCookie(c))
headers.foreach(h => postBuilder.addHeader(h._1, h._2))
val request: Request = postBuilder.build()
asyncHttpClient.executeRequest(request)
}
}
This is how I used it with Silhouette CookieAuthenticator
"cookie" is a header called "Set-Cookie" from login response.
WsExtend.postFile(
url=url,
files = List("fileparamname" -> filepath),
bodyParams = List("albumName" -> albumName),
headers = Map("Cookie" -> cookie)

- 1,633
- 1
- 20
- 28