2

我正在开发一个 Web 服务,它提供一些相对较大的文件,每个文件都是在请求时动态创建的。就我而言,这是一个包含一堆文件的 ZIP 存档文件,但我认为其他类型的动态创建的文件也会出现同样的问题。

问题是我想避免在磁盘上创建 ZIP 文件,而只是将其直接流式传输到 HTTP 响应。我想到的一种方法是使用分块流式传输,这意味着流式传输参与者当时发送一个块,并在发送下一个块之前“等待”响应者的确认。(参见sendStreamingResponsehttps://github.com/spray/spray/blob/release/1.1/examples/spray-routing/on-spray-can/src/main/scala/spray/examples/DemoService.scala的示例)

不幸的是,我能找到的所有示例都显示了在您的流是预定义的情况下如何做到这一点,但我不太确定在其他未来准备数据流时,最好的方法是什么。

在我的例子中,有一个Future由 HTTP 请求启动的,它完成了所有繁重的获取文件的工作,并将它们写入java.util.zip.ZipOutputStream. 但在 Spray 中流式传输的工作方式恰恰相反,因为流式传输参与者需要在准备好数据时拉取数据——我不能只是将所有数据推送到流中。

这是一个熟悉的用例吗?解决它的最佳方法是什么?

4

1 回答 1

0

我认为如果我们生成一个Steam[Byte]. 我还没有尝试过,但这样的事情应该可以工作(我过去做过类似的事情,包括动态图像调整大小和提供大文件)。

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 的流编组器将自动生成分块响应。

于 2015-11-12T14:16:20.817 回答