I would like to be able to identify when a stream completes, is cancelled or fails.
I have the following controller action:
def downloadAction(streamer: (String, String) => Future[ Either[ String, Result ] ],snr: String, fName: String ) = Action.async { implicit request =>
streamer( snr, fName ).map {
case Left(err) => Ok(views.html.errorPage( err ) )
case Right(result) => result.withHeaders(CONTENT_DISPOSITION -> s"attachment; filename=$fName")
}
}
My first approach was to add an onComplete to the streamer Future:
def downloadAction(streamer: ( String, String ) => Future[ Either[ String, Result ] ], snr: String, fName: String ) = Action.async { implicit request =>
val startTs = System.currentTimeMillis
val streamFut = streamer(snr, fName).map {
case Left(err) => Ok(views.html.errorPage(err))
case Right(result) => result.withHeaders(CONTENT_DISPOSITION -> s"attachment; filename=$fName")
}.onComplete( _ => {
val requestTime = System.currentTimeMillis - startTs
Logger.info(s"${request.header.method} ${request.header.uri} took ${requestTime}ms and returned ${result.header.status}")
})
streamFut
}
This timing values were of the order of 100ms, when a 100Mb download was clearly taking a few minutes. So this approach was not correct.
I realised that because the streamerFut was originally coming from a HttpEntity.Streamed/HttpEntity.Chunked, then the Future completes quite quickly, even though the streaming is ongoing. I guess that this approach might work for HttpEntity.Strict but not for HttpEntity.Streamed/HttpEntity.Chunked
I am looking for a server side solution before I consider looking at client side javascript.