Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Using custom multipart body parser that uses specified dir to save files
package controllers;
import java.io.File;
import java.util.List;
import play.mvc.BodyParser;
import play.mvc.BodyParser.Of;
import play.mvc.Controller;
import play.mvc.Http.MultipartFormData;
import play.mvc.Http.MultipartFormData.FilePart;
import play.mvc.Http.RequestBody;
import play.mvc.Result;
import utils.CustomParsers;
import views.html.index;
public class Application extends Controller {
public static class PermanentMultipartFormData implements BodyParser {
//location to save the files
private final File dir = new File("data");
@Override
public play.api.mvc.BodyParser<RequestBody> parser(int maxLength) {
return CustomParsers.permanentMultipartFormData(dir, maxLength);
}
}
@Of(PermanentMultipartFormData.class)
public static Result upload() {
MultipartFormData md = request().body().asMultipartFormData();
//do your thing
}
public static Result index() {
return ok(index.render("Your new application is ready."));
}
}
package utils
import java.io.File
import play.api.mvc._
import play.mvc.Http.RequestBody
import play.api.mvc.BodyParsers._
import parse._
import play.core.j.JavaParsers.DefaultRequestBody
import play.api.libs.iteratee.Iteratee
import play.api.mvc.MultipartFormData._
import play.api.libs.Files.TemporaryFile
import java.io.FileOutputStream
import scala.collection.JavaConverters._
object CustomParsers {
case class MultipartRequestBody(multipart: MultipartFormData[File]) extends RequestBody {
override lazy val asMultipartFormData = {
new play.mvc.Http.MultipartFormData {
lazy val asFormUrlEncoded = {
multipart.asFormUrlEncoded.mapValues(_.toArray).asJava
}
lazy val getFiles = {
multipart.files.map { file =>
new play.mvc.Http.MultipartFormData.FilePart(
file.key, file.filename, file.contentType.orNull, file.ref)
}.asJava
}
}
}
}
private def orDefault(maxLength: Int) = if (maxLength < 0) parse.DEFAULT_MAX_TEXT_LENGTH else maxLength
type PartHandler[A] = PartialFunction[Map[String, String], Iteratee[Array[Byte], A]]
def permanentMultipartFormData(dir: File, maxLength: Int): BodyParser[RequestBody] = {
parse.maxLength(orDefault(maxLength), parse.multipartFormData(handleFilePartAsPermanentFile(dir))).map {
_.fold(
_ => DefaultRequestBody(isMaxSizeExceeded = true),
multipart =>
MultipartRequestBody(multipart))
}
}
def handleFilePartAsPermanentFile(dir: File): PartHandler[FilePart[File]] = {
Multipart.handleFilePart {
case Multipart.FileInfo(partName, filename, contentType) =>
val file = new File(dir, filename)
Iteratee.fold[Array[Byte], FileOutputStream](new java.io.FileOutputStream(file)) { (os, data) =>
os.write(data)
os
}.map { os =>
os.close()
file
}
}
}
}
@satishkvemula

Hi,

Thank you very much for sharing this code, as I have a very similar need.

At the same time, our http end point is currently overloaded to handle different content-types, either multipart of urlencoded content-types.

Is there any way, I can get hold of the Content-Type, in the PermanentMultipartFormData.parser method, so that I can return different parsers depending on content type.

I see that BodyParsers.parse.anyContent is being passed a request object, but I am not sure how to access that in the mentioned method. The Threadlocal Http Context itself seems uninitialized at this point of time.

Please let me know. I can live with single parser option too, where during parsing it can figure out what content -type it is going to be.

regards
Satish Vemula

@msegeya

adding the import below to the scala code

import scala.concurrent.ExecutionContext.Implicits.global

Fixed some errors that i faced while using this code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.