51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

捕获由withSizeLimit指令抛出的EntityStreamSizeException。

英文:

How to catch EntityStreamSizeException thrown by withSizeLimit Directive

问题 {#heading}

我已创建了一个在akka http中用于上传文件的POST请求。

以下是我的代码:

final val MEDIA_FILE_UPLOAD_MAX_SIZE = 30 * 1024 * 1024

def uploadMediaObjectForASite(): Route = path("Some path") { userId => post { parameter(Symbol("location_id").as[String]) { locationId => withSizeLimit(MEDIA_FILE_UPLOAD_MAX_SIZE) { withRequestTimeout(120.seconds) { entity(as[Multipart.FormData]) { formData => val metadataList = List(TITLE, DESCRIPTION, UPLOADED_BY) // 提取文件部分并开始上传过程 } } } } } }

如果我使用大于30MB的文件,我在Postman中会得到一个400 BadRequest的错误,消息如下:

EntityStreamSizeException: incoming entity size (47350868) exceeded size limit (31457280 bytes)! This may have been a parser limit (set via akka.http.[server|client].parsing.max-content-length), a decoder limit (set via akka.http.routing.decode-max-size), or a custom limit set with withSizeLimit.

我尝试了以下两种方法:

a) 使用handleException指令:

val customExceptionHandler: ExceptionHandler = ExceptionHandler {
  case _: EntityStreamSizeException =>
    complete(StatusCodes.PayloadTooLarge, "文件大小超过了30MB的限制")
}

def uploadMediaObjectForASite(): Route = path("Some path") { userId => post { handleException(customExceptionHandler) { parameter(Symbol("location_id").as[String]) { locationId => withSizeLimit(MEDIA_FILE_UPLOAD_MAX_SIZE) { withRequestTimeout(120.seconds) { entity(as[Multipart.FormData]) { formData => val metadataList = List(TITLE, DESCRIPTION, UPLOADED_BY) // 提取文件部分并开始上传过程 } } } } } } }

b) 使用handleRejection指令:

val customRejectionHandler: RejectionHandler = RejectionHandler.newBuilder()
  .handle {
    case EntityStreamSizeException(limit, actualSize) =>
      complete(StatusCodes.PayloadTooLarge, s"文件大小超过了${limit}字节的限制")
  }
  .result()

def uploadMediaObjectForASite(): Route = path("Some path") { userId => post { handleRejection(customRejectionHandler) { parameter(Symbol("location_id").as[String]) { locationId => withSizeLimit(MEDIA_FILE_UPLOAD_MAX_SIZE) { withRequestTimeout(120.seconds) { entity(as[Multipart.FormData]) { formData => val metadataList = List(TITLE, DESCRIPTION, UPLOADED_BY) // 提取文件部分并开始上传过程 } } } } } } }

但是这两种方法都不起作用。请问如何捕获此异常并提供自定义消息? 英文:

I have created a post request in akka http to upload a file

Here is my code

final val MEDIA_FILE_UPLOAD_MAX_SIZE = 30 * 1024 * 1024
`def uploadMediaObjectForASite(): Route = path("Some path") {
userId =>
post {
parameter(Symbol("location_id").as[String]) {
locationId =>
withSizeLimit(MEDIA_FILE_UPLOAD_MAX_SIZE) {
withRequestTimeout(120.seconds) {
entity(as[Multipart.FormData]) {
formData =>
val metadataList = List(TITLE, DESCRIPTION, UPLOADED_BY)
// extract file parts and start the upload process
}
}
}
}
}
}
`

If I use a file greater than 30MB I get a 400 BadRequest in postman with following message

> EntityStreamSizeException: incoming entity size (47350868) exceeded size limit (31457280 bytes)! This may have been a parser limit (set via akka.http.[server|client].parsing.max-content-length), a decoder limit (set via akka.http.routing.decode-max-size), or a custom limit set with withSizeLimit.

I have tried following approach
a) using handleException directive

 val customExceptionHandler: ExceptionHandler = ExceptionHandler {
    case _: EntityStreamSizeException =>
      complete(StatusCodes.PayloadTooLarge, "File size exceeded the limit of 30MB")
  }

def uploadMediaObjectForASite(): Route = path("Some path") { userId => post { handleException(customExceptionHandler) { parameter(Symbol("location_id").as[String]) { locationId => withSizeLimit(MEDIA_FILE_UPLOAD_MAX_SIZE) { withRequestTimeout(120.seconds) { entity(as[Multipart.FormData]) { formData => val metadataList = List(TITLE, DESCRIPTION, UPLOADED_BY) // extract file parts and start the upload process } } } } } } }


b) using handleRejection directive

val customRejectionHandler: RejectionHandler = RejectionHandler.newBuilder()
    .handle {
      case EntityStreamSizeException(limit, actualSize) =>
        complete(StatusCodes.PayloadTooLarge, s"File size exceeded the limit of ${limit} bytes")
    }
    .result()

def uploadMediaObjectForASite(): Route = path("Some path") { userId => post { handleRejection(customRejectionHandler) { parameter(Symbol("location_id").as[String]) { locationId => withSizeLimit(MEDIA_FILE_UPLOAD_MAX_SIZE) { withRequestTimeout(120.seconds) { entity(as[Multipart.FormData]) { formData => val metadataList = List(TITLE, DESCRIPTION, UPLOADED_BY) // extract file parts and start the upload process } } } } } } }


But none of them works

How can I catch this exception and provide custom message.

答案1 {#1}

得分: 0

You may use the directives handleExceptions()/handleRejections() like this:

  val handleErrors = handleExceptions(customExceptionHandler) & handleRejections(customRejectionHandler)

val routes: Route = { handleErrors { concat(uploadMediaObjectForASite, myOtherRoute) } }

Also see this working example. Not sure why your approach is not working though, although I just see the handleExceptions directive in 10.5.2 (and not handleException). Also, I see that the response PayloadTooLarge is deprecated in favor of ContentTooLarge. 英文:

You may use the directives handleExceptions()/handleRejections() like this:

  val handleErrors = handleExceptions(customExceptionHandler) &  handleRejections(customRejectionHandler)
`val routes: Route = {
handleErrors {
concat(uploadMediaObjectForASite, myOtherRoute)
}
}
`

Also see this working example. Not sure why your approach is not working though, although I just see the handleExceptionsdirective in 10.5.2 (and not handleException). Also I see that the response PayloadTooLarge is deprecated in favour of ContentTooLarge.


赞(2)
未经允许不得转载:工具盒子 » 捕获由withSizeLimit指令抛出的EntityStreamSizeException。