Hi,
I try to stream a ZIP file from files stored in a MongoDB. To create the ZIP I use
this example code. I use ReactiveMongo which provides every file as a Enumerator[Array[Byte]]. I've created a method that transforms this Enumerator into an InputStream which is used to ZIP the file:
implicit def enumeratorToInputStream(enumerator: Enumerator[Array[Byte]]): InputStream = {
val pos = new PipedOutputStream()
val pis = new PipedInputStream(pos)
val it = Iteratee.foreach[Array[Byte]](pos.write)
enumerator.onDoneEnumerating(pos.close()) |>>> it onComplete {
case Failure(e) =>
logger.error("Got exception on converting enumerator to stream", e)
case Success(_) =>
logger.info("Successfully feed all enumerator data into the input stream")
}
pis
}
My Play code looks as follow:
val filesToZip: immutable.Iterable[StreamedZip.ZipSource] = files.map { file =>
(file.filename.getOrElse(file.id.stringify + ".pdf"), () => enumeratorToInputStream(file.content))
}
val source: Source[ByteString, _] = Source[StreamedZip.ZipSource](filesToZip).via(StreamedZip())
val filename = Messages("main.zip.document.name")
Ok.chunked(source)
.as("application/zip")
.withHeaders(CONTENT_DISPOSITION -> s"attachment; filename=$filename")
But this does only work with one file. If I try to create a ZIP from multiple files then the response contains only the string java.net.SocketException: Connection reset. I do not see any stack trace in my logs or in the console. If I debug the code then I see that only one file will be processed. The others will be ignored.
If I try to materialize the stream directly in my action, then all works as expected. All files will be processed.
Does anyone have an idea what could cause this issue? Any help would be highly appreciated.
Best regards,
Christian