英文:
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 handleExceptions
directive in 10.5.2 (and not handleException
). Also I see that the response PayloadTooLarge
is deprecated in favour of ContentTooLarge
.