PlayFramework 2.4.6 错误 413 请求实体太大

PlayFramework 2.4.6 error 413 Request Entity Too Large

我正在使用 PlayFramework 2.4.6,尝试上传一个多部分文件(大小 18M)并且服务器 returns 出现以下错误:

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

我环顾四周并尝试了以下方法但没有成功:

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

其中 none 解决了问题。

这也是 Stacktrace:

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.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.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]

解决了这个问题:

play.http.parser.maxDiskBuffer = 100MB

parsers.anyContent.maxLength = 100MB

我在发送大表格时遇到了同样的问题,play.http.parser.maxMemoryBuffer=4MB 解决了。

请参阅有关 Play 使用的内存和磁盘缓冲区的文档: 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.

因此,由于您正在尝试上传多部分文件,因此您需要将 play.http.parser.maxDiskBuffer 增加到大于 18MB。

因此,将此添加到您的 application.conf 应该可以解决问题:

play.http.parser.maxDiskBuffer=100MB

对于那些遇到 Play Framework 2 问题的人。6.x 请参阅 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:

在application.conf中添加以下内容:

play.http.parser.maxMemoryBuffer = 5MB

就我而言,我使用的是 AnyContent 解析器。我将 controller 定义更改为以下以使我的代码工作

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
...
}
}