1

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.

0 Answers0