Eri*_*rik 4 scala playframework playframework-2.0
我试图在http://www.playframework.org/documentation/2.0/ScalaStream上实现类似于"发送大量数据"的第一个例子.
我的不同之处在于我有多个文件要在响应中连接.它看起来像这样:
def index = Action {
val file1 = new java.io.File("/tmp/fileToServe1.pdf")
val fileContent1: Enumerator[Array[Byte]] = Enumerator.fromFile(file1)
val file2 = new java.io.File("/tmp/fileToServe2.pdf")
val fileContent2: Enumerator[Array[Byte]] = Enumerator.fromFile(file2)
SimpleResult(
header = ResponseHeader(200),
body = fileContent1 andThen fileContent2
)
Run Code Online (Sandbox Code Playgroud)
}
发生的事情是只有第一个文件的内容在响应中.
稍微简单如下的一些工作正常:
fileContent1 = Enumerator("blah" getBytes)
fileContent2 = Enumerator("more blah" getBytes)
SimpleResult(
header = ResponseHeader(200),
body = fileContent1 andThen fileContent2
)
Run Code Online (Sandbox Code Playgroud)
我错了什么?
我从阅读游戏代码中获得了大部分内容,所以我可能会误解,但从我所看到的:Enumerator.fromFile
函数(Iteratee.scala [docs] [src])创建一个枚举器,当应用于Iteratee[Byte, Byte]
追加Input.EOF
到完成从文件中读取后,Iteratee的输出.
根据Play!你链接到您的文档例如得在枚举结束手动添加一个Input.EOF(Enumerator.eof的别名).我认为,将Input.EOF自动附加到文件字节数组的末尾是您只返回一个文件的原因.
播放控制台中等效的简单示例如下:
scala> val fileContent1 = Enumerator("blah") andThen Enumerator.eof
fileContent1: play.api.libs.iteratee.Enumerator[java.lang.String] = play.api.libs.iteratee.Enumerator$$anon$23@2256deba
scala> val fileContent2 = Enumerator(" and more blah") andThen Enumerator.eof
fileContent2: play.api.libs.iteratee.Enumerator[java.lang.String] = play.api.libs.iteratee.Enumerator$$anon$23@7ddeef8a
scala> val it: Iteratee[String, String] = Iteratee.consume[String]()
it: play.api.libs.iteratee.Iteratee[String,String] = play.api.libs.iteratee.Iteratee$$anon$18@6fc6ce97
scala> Iteratee.flatten((fileContent1 andThen fileContent2) |>> it).run.value.get
res9: String = blah
Run Code Online (Sandbox Code Playgroud)
修复,虽然我还没有尝试过这个,但是会更深入一些并Enumerator.fromCallback
直接使用函数并传递一个自定义检索器函数,该函数一直保持返回,Array[Byte]
直到你想要连接的所有文件都被读取.请参阅fromStream
函数的实现以查看默认值以及如何修改它.
如何执行此操作的示例(改编自Enumerator.fromStream
):
def fromFiles(files: List[java.io.File], chunkSize: Int = 1024 * 8): Enumerator[Array[Byte]] = {
val inputs = files.map { new java.io.FileInputStream(_) }
var inputsLeftToRead = inputs
Enumerator.fromCallback(() => {
def promiseOfChunkReadFromFile(inputs: List[java.io.FileInputStream]): Promise[Option[Array[Byte]]] = {
val buffer = new Array[Byte](chunkSize)
(inputs.head.read(buffer), inputs.tail.headOption) match {
case (-1, Some(_)) => {
inputsLeftToRead = inputs.tail
promiseOfChunkReadFromFile(inputsLeftToRead)
}
case (-1, None) => Promise.pure(None)
case (read, _) => {
val input = new Array[Byte](read)
System.arraycopy(buffer, 0, input, 0, read)
Promise.pure(Some(input))
}
}
}
promiseOfChunkReadFromFile(inputs)
}, {() => inputs.foreach(_.close())})
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1334 次 |
最近记录: |