使用 Spray 发送大文件

Sending large files with Spray

我知道以前有人问过非常相似的问题。但是我认为我在 google/Whosebug 上找到的解决方案不适合我。

我开始用 Scala/Spray 编写一些 Web 服务,似乎发送大文件而不消耗大量内存的最佳方法是使用流编组。这样 Spray 将发送 http 块。两个问题:

  1. 是否可以在不使用 HTTP 块且不将整个文件读入内存的情况下发送文件?

  2. AFAIK akka.io 一次只处理一个写入,这意味着它可以缓冲一个写入,直到它被完全传递给 O/S 内核。是否可以为每个 HTTP 响应告诉 Spray 内容的长度?此后 Spray 将请求新数据(通过 akka 消息),直到完成整个内容长度。例如,我表示我的内容长度是 100 字节。 Spray 向我的演员发送请求数据的消息,我提供 50 个字节。将此数据传递到 O/S 后,spray 会发送另一条消息请求新数据。我提供剩余的50个字节...然后响应完成。

Is it possible to send the file without using HTTP chunks [on the wire]

是的,您需要启用无块流。参见 http://spray.io/documentation/1.2.4/spray-routing/advanced-topics/response-streaming/

无论您是使用 Stream 编组器还是自己提供 MessageChunk 响应,Chunkless 流式传输都有效。请参阅以下示例。

without reading the entire file into memory

是的,如果您以 Stream[Array[Byte]]Stream[ByteString].

形式提供数据,那应该可以工作

[...] Thereafter Spray would ask for new data [...]

这实际上几乎就像它已经起作用了:如果您手动提供块,您可以请求一条自定义 Ack 消息,该消息将在 spray-can 层能够处理下一部分时返回给您。请参阅 this example 以了解如何从喷雾路线流式传输。

I indicate my content length is 100 bytes

预先说明:在 HTTP 中,您不需要为响应指定 content-length,因为可以通过关闭连接来分隔响应 body,如果无块流式传输,spray 就是这样做的是启用。但是,如果您不想关闭连接(因为您会失去此持久连接),您现在可以在 ChunkedResponseStart 消息中指定明确的 Content-Length header(请参阅 #802) 这将阻止关闭连接。