我正在开发一个服务于一些相对较大的文件的Web服务,每个文件都是在请求时动态创建的。在我的例子中,这是一个ZIP存档文件,其中包含一堆文件,但我认为其他类型的动态创建文件也会出现同样的问题。
问题是我想避免在磁盘上创建ZIP文件,而是直接将其直接传输到HTTP响应。
我想到的一种方法是使用分块流,这意味着流媒体播放器此时发送一个块,并在发送下一个块之前“等待”来自响应者的确认。 (请参阅https://github.com/spray/spray/blob/release/1.1/examples/spray-routing/on-spray-can/src/main/scala/spray/examples/DemoService.scala中的sendStreamingResponse
)
不幸的是,我找到的所有示例都显示了如何在预定义流时执行此操作,但我不太确定在其他未来准备数据流时,最好的方法是什么。
就我而言,HTTP请求启动了Future
,它完成了获取文件并将其写入java.util.zip.ZipOutputStream
的所有繁重工作。但是Spray中流式传输的方式恰恰相反,因为流媒体演员需要在数据准备就绪时拉取数据 - 我不能只将所有数据推送到流中。
这是一个熟悉的用例,解决它的最佳方法是什么?
答案 0 :(得分:0)
如果我们生成Steam[Byte]
,我认为我们可以使用Spray的内置编组程序。我还没有尝试过,但这样的事情应该有用(我过去做过类似的事情,动态图像调整大小并提供大文件)。
val pipeIn = new PipedInputStream()
val pipeOut = new PipedOutputStream(pipeIn)
val out = new ByteArrayOutputStream()
val st = new ZipOutputStream(out)
Future{
writeToZip(st)
out.writeTo(pipeOut)
}
val streamResponse: Stream[Byte] = Stream.continually(pipeIn.read).takeWhile(_ != -1).map(_.toByte)
complete(streamResponse)
Spray的流marshaller会自动产生分块响应。