This is my code the same code is working in play 2.1.5 but I am unable to create war file in play 2.1.5 so I switched to play 2.4.3 and now in response it is coming that 400 bad request client
is sending wrong syntactically even post rest api is not hitting. Can some tell me what I am missing?
import play.api._
import play.api.libs.ws._
import play.api.mvc._
//import javax.inject.Inject
import play.api.Play.current
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.libs.ws.WSAuthScheme
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 {
Ok(views.html.index("Your new application is ready."))
}
def postUpload=Action(parse.multipartFormData){request=>
val groupingType= request.body.dataParts("Grouping type").mkString
val email=request.body.dataParts("NotificationRecepients").mkString
val custId=request.body.dataParts("CustomerId").mkString
val custIdFinal:Int=custId.toInt
request.body.file("file").map { file =>
val file1=file.ref.file.getAbsolutePath;
val fileName = file.filename
val contentType = file.contentType
//file.ref.moveTo(new File("/home/kanchan/Desktop/"+fileName),true)
val user = "myUser";
val password = "myPassword";
val encodedCredentials =
new String(encodeBase64("%s:%s".format(user, password).getBytes))
val asyncHttpClient:AsyncHttpClient =WS.client.underlying
val postBuilder = asyncHttpClient.preparePost(url)
val builder = postBuilder
.addHeader("Authorization", "Basic " + encodedCredentials)
.addBodyPart(new StringPart("selectedGroupType", "Functional Grouping", "UTF-8"))
.addBodyPart(new StringPart("mailRecipients", "kancgupt@cisco.com", "UTF-8"))
.addBodyPart(new StringPart("selectedFile", "Sample_group_upload_file.xlsx", "UTF-8"))
.addBodyPart(new FilePart("file",new File("/home/kanchan/Downloads/Sample_group_upload_file.xlsx")))
val response = asyncHttpClient.executeRequest(builder.build()).get();
Ok(response.getResponseBody)
}.getOrElse {
Ok( "Missing file")
}
}
}
Play version 2.4.3
sbt:0.13.8
getting following error:
Apache Tomcat/6.0.39 - Error report
HTTP Status 400 - Bad Request
type Status report
message Bad Request
description The request sent by the client was syntactically incorrect.
Apache Tomcat/6.0.39
You describing something really strange. I took your code, curl, REST server echo (http://httpbin.org, exactly http://httpbin.org/post url), create new play-scala application with the 2.4.3 play. It works like a charm.
Code:
package controllers
import play.api._
import play.api.libs.ws._
import play.api.mvc._
import play.api.Play.current
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.libs.ws.WSAuthScheme
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 Original extends Controller {
def postUpload = Action(parse.multipartFormData) { request =>
val groupingType = request.body.dataParts("Groupingtype").mkString
val email = request.body.dataParts("NotificationRecepients").mkString
val custId = request.body.dataParts("CustomerId").mkString
val custIdFinal: Int = custId.toInt
request.body.file("file").map { file =>
val file1 = file.ref.file.getAbsolutePath;
val fileName = file.filename
val contentType = file.contentType
val url = "http://httpbin.org/post"
val user = "myUser";
val password = "myPassword";
val encodedCredentials =
new String(encodeBase64("%s:%s".format(user, password).getBytes))
val asyncHttpClient: AsyncHttpClient = WS.client.underlying
val postBuilder = asyncHttpClient.preparePost(url)
val builder = postBuilder
.addHeader("Authorization", "Basic " + encodedCredentials)
.addBodyPart(new StringPart("selectedGroupType", groupingType, "UTF-8"))
.addBodyPart(new StringPart("mailRecipients", email, "UTF-8"))
.addBodyPart(new StringPart("selectedFile", fileName, "UTF-8"))
.addBodyPart(new FilePart("file", new File(file1)))
val response = asyncHttpClient.executeRequest(builder.build()).get();
Ok(response.getResponseBody)
}.getOrElse {
Ok("Missing file")
}
}
}
curl command (from the project root folder):
curl -i -X POST \
-H "Content-Type:multipart/form-data" \
-F "Groupingtype=Groupingtype" \
-F "NotificationRecepients=NotificationRecepients" \
-F "CustomerId=123" \
-F "file=@app/controllers/Application.scala" \
'http://localhost:9000/post'
curl response:
HTTP/1.1 100 Continue
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Tue, 06 Oct 2015 18:38:11 GMT
Content-Length: 3122
{
"args": {},
"data": "",
"files": {
"file": "package controllers..."
},
"form": {
"mailRecipients": "NotificationRecepients",
"selectedFile": "Application.scala",
"selectedGroupType": "Groupingtype"
},
"headers": {
"Accept": "*/*",
"Authorization": "Basic bXlVc2VyOm15UGFzc3dvcmQ=",
"Content-Length": "3215",
"Content-Type": "multipart/form-data; boundary=2EmAF3UE9xSuA6KQpUS3q-Ohzkp0f_7-8",
"Host": "httpbin.org",
"User-Agent": "AHC/1.0"
},
"json": null,
"origin": "111.111.111.111",
"url": "http://httpbin.org/post"
}
Try to create new simple project and use my code - then migrate yours in to this new project - maybe you will find something. It could be some wrong migration steps from 2.1.5 or so.
my build.sbt
name := """scala-send-multipart-clean"""
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.11.6"
libraryDependencies ++= Seq(
jdbc,
cache,
ws,
specs2 % Test
)
resolvers += "scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"
// Play provides two styles of routers, one expects its actions to be injected, the
// other, legacy style, accesses its actions statically.
routesGenerator := InjectedRoutesGenerator
my project/plugins.sbt
// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.4.3")
// web plugins
addSbtPlugin("com.typesafe.sbt" % "sbt-coffeescript" % "1.0.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-less" % "1.0.6")
addSbtPlugin("com.typesafe.sbt" % "sbt-jshint" % "1.0.3")
addSbtPlugin("com.typesafe.sbt" % "sbt-rjs" % "1.0.7")
addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-mocha" % "1.1.0")
my project/build.properties
#Activator-generated Properties
#Wed Oct 07 00:44:35 EEST 2015
template.uuid=7da33b5a-3aef-4d2e-b318-dae93632b999
sbt.version=0.13.8
java version "1.8.0_40", updated to the "build 1.8.0_60-b27" - no difference.
I am getting this [StringPart name=selectedGroupType contentType=UTF-8
charset=US-ASCII tranferEncoding=8bit contentId=null
dispositionType=null, StringPart name=mailRecipients contentType=UTF-8
charset=US-ASCII tranferEncoding=8bit contentId=null
dispositionType=null, StringPart name=selectedFile contentType=UTF-8
charset=US-ASCII tranferEncoding=8bit contentId=null
dispositionType=null, FilePart name=file
contentType=application/octet-stream charset=null
tranferEncoding=binary contentId=null dispositionType=null
filename=Sample_group_upload_file.xlsx]
It is the way toString
is realised in the Parts. That's all, it does not tell something about "correct" or "not correct".
My results for
println(builder.build().getParts())
is
[StringPart name=selectedGroupType contentType=UTF-8 charset=US-ASCII tranferEncoding=8bit contentId=null dispositionType=null, StringPart name=mailRecipients contentType=UTF-8 charset=US-ASCII tranferEncoding=8bit contentId=null dispositionType=null, StringPart name=selectedFile contentType=UTF-8 charset=US-ASCII tranferEncoding=8bit contentId=null dispositionType=null, FilePart name=file contentType=application/octet-stream charset=null tranferEncoding=binary contentId=null dispositionType=null filename=multipartBody1697314279257602964asTemporaryFile]
As you see it very similar to yours, but if you will output names and values for the string part, I am pretty sure you will receive both:
import scala.collection.JavaConversions._
...
builder.build().getParts().map{ part =>
if(part.isInstanceOf[StringPart]){
val stringPart: StringPart = part.asInstanceOf[StringPart]
println(stringPart.getName() + ":" + stringPart.getValue())
}
}
results:
selectedGroupType:Groupingtype
mailRecipients:NotificationRecepients
selectedFile:Application.scala