英文:
How to catch EntityStreamSizeException thrown by withSizeLimit Directive
问题
我已创建了一个在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
得分: 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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论