21
votes

I am using PlayFramework 2.4.6, trying to upload a multipart file (size 18M) and the server returns the following error:

For request 'POST /api/myEndpoint' [Request Entity Too Large]

I have looked around and tried the following with out success:

  1. play.http.parser.maxMemoryBuffer=2000000K
  2. parsers.MultipartFormData.maxLength=1024000K
  3. play.http.parser.maxDiskBuffer=2000000K
  4. Action.async(parse.anyContent(Some(1024*200L)))

And none of them solves the problem.

Here is the Stacktrace as well:

14:57:33.128 [New I/O worker #2] [error] -     p.c.server.netty.RequestBodyHandler - Exception caught in RequestBodyHandler
java.nio.channels.ClosedChannelException: null
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.setInterestOps(AbstractNioWorker.java:506) [netty-3.10.4.Final.jar:na]
at org.jboss.netty.channel.socket.nio.AbstractNioWorker$1.run(AbstractNioWorker.java:455) [netty-3.10.4.Final.jar:na]
at org.jboss.netty.channel.socket.ChannelRunnableWrapper.run(ChannelRunnableWrapper.java:40) [netty-3.10.4.Final.jar:na]
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.processTaskQueue(AbstractNioSelector.java:391) [netty-3.10.4.Final.jar:na]
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:315) [netty-3.10.4.Final.jar:na]
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:89) [netty-3.10.4.Final.jar:na]
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178) [netty-3.10.4.Final.jar:na]
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108) [netty-3.10.4.Final.jar:na]
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) [netty-3.10.4.Final.jar:na]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_65]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_65]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_65]
5

5 Answers

34
votes

Solved the problem with this:

play.http.parser.maxDiskBuffer = 100MB

parsers.anyContent.maxLength = 100MB
26
votes

I was having the same problem sending a large form and play.http.parser.maxMemoryBuffer=4MB solved it.

20
votes

See this documentation about the memory and disk buffers Play uses: https://www.playframework.com/documentation/2.4.x/ScalaBodyParsers#Max-content-length

Text based body parsers (such as text, json, xml or formUrlEncoded) use a max content length because they have to load all the content into memory. By default, the maximum content length that they will parse is 100KB. It can be overridden by specifying the play.http.parser.maxMemoryBuffer property in application.conf:

play.http.parser.maxMemoryBuffer=128K

For parsers that buffer content on disk, such as the raw parser or multipart/form-data, the maximum content length is specified using the play.http.parser.maxDiskBuffer property, it defaults to 10MB. The multipart/form-data parser also enforces the text max length property for the aggregate of the data fields.

So, since you're trying to uploading a multipart file, you'll need to increase the play.http.parser.maxDiskBuffer to something >18MB.

So, adding this to your application.conf should fix it:

play.http.parser.maxDiskBuffer=100MB
2
votes

For those who are facing issue with Play Framework 2.6.x see documentation at https://www.playframework.com/documentation/2.6.x/ScalaBodyParsers

Max content length Text based body parsers (such as text, json, xml or formUrlEncoded) use a max content length because they have to load all the content into memory. By default, the maximum content length that they will parse is 100KB. It can be overridden by specifying the play.http.parser.maxMemoryBuffer property in application.conf:

add following in application.conf:

play.http.parser.maxMemoryBuffer = 5MB
0
votes

In my case, I am using an AnyContent Parser. I changed the controller definition to following to make my code work

def newQuestion = silhouette.SecuredAction.async(parse.maxLength(1024 * 1024, parse.anyContent)(ActorMaterializer()(ActorSystem("MyApplication")))){

  implicit request => {
      println("got request with body:" + request.body)
      val anyBodyErrors: Either[MaxSizeExceeded, AnyContent] = request.body
      anyBodyErrors match {
        case Left(size) => {
          Future {
            EntityTooLarge(Json.toJson(JsonResultError(messagesApi("error.entityTooLarge")(langs.availables(0)))))
          }
        }
        case Right(body) => {

          //val body:AnyContent = request.body
          val jsonBodyOption = body.asJson
...
}
}