我想在Play中编写应用程序!框架2.2.x作为异步方法和play.api.libs.iterattee
包的练习。我想要做的是在其正文中获取一个带有大文件上传的POST请求,并按块发送它,作为下载到单独的请求。
" Play for Scala" book和this example引导我接收请求中的文件,我可以在自定义Iteratee
中定义的任何BodyParser
中累积或迭代。关于serving a chunked response,我需要为响应提供Enumerator
- 例如Ok.chunked(enumerator)
,当枚举器提供新的块时,它将提供给客户端。
既然我想把它们放在一起,我似乎无法找到一种优雅且反应灵敏的方式来将新数据块从上传客户端异步传播到下载。对于"转发"似乎并不是一个好方法。由Iteratee
(在这种情况下在BodyParser
中)收到的数据到新的Enumerator
(在这种情况下是向响应提供输出的数据)。
我想出了两种方法,但对我来说,它们似乎都不够好:
使用play.api.libs.iteratee.Concurrent.boradcast
生成Channel
和Enumerator
,并在我的BodyParser中将每个收到的块推送到Channel
。 Channels
不具备Enumerator
所拥有的属性 - 枚举器在应用Iteratee
之前不会产生新值,直到Channel
消耗旧值。
如果我这样做的话,如果上传者的互联网连接速度比下载器快,那么我会有一个"肿胀" Actor
占用越来越多的内存,而不是一次处理一个块。
创建一个代理akka Actor
并将上传的文件chunk by chunk发送给它,只有在下一个文件被下载程序占用后才发送下一个文件。但在这种情况下,发送到下载程序的每个块的确认必须通过Iteratee
代理,以便上传者Enumerator
将另一个块发送到代理。这对我来说似乎是不必要的开销。
我想我的问题有两个:
Iteratee
生成{{1}}收到的值?答案 0 :(得分:2)
您可以使用Concurrent.joined
:
val (iteratee, enumerator) = Concurrent.joined[Array[Byte]]