post {
extractRequestContext { ctx =>
val uploadF = Future {
Files.createDirectories(destPath.getParent)
Files.createTempFile(destPath.getParent, "", ".tmp")
}(filesystemEc) flatMap { tmpPath =>
withTemporaryFile(tmpPath){ () =>
for {
_ <- ctx.request.entity.withSizeLimit(MaxUploadableSize).dataBytes.runWith(FileIO.toPath(tmpPath))
lastModifiedTime <- commit(tmpPath, destPath)
} yield lastModifiedTime
}
}
onComplete(uploadF) {
case Success(lastModifiedTime) =>
complete("")
case Failure(ex: FileSystemException) if {
val lowerMessage = ex.getMessage.toLowerCase
lowerMessage.contains("disk quota exceeded") ||
lowerMessage.contains("no space left on device")
} =>
complete(HttpResponse(
status = StatusCodes.RequestEntityTooLarge,
entity = HttpEntity("Disk quota exceeded")
))
case Failure(ex) =>
throw ex
}
}
}
...
private def withTemporaryFile[T](tempFile: Path)
(body: () => Future[T]): Future[T] = {
val result = body()
result.recoverWith {
case e =>
Future(Files.deleteIfExists(tempFile))
.flatMap(_ => result)
}
}