为什么我未能在普查员身体SimpleResult结合?(Why am I Failing to co

2019-09-23 01:54发布

我试着去实现“发送大量的数据”下,在类似于第一例东西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
  )

}

什么情况是,只有第一个文件的内容是在响应中。

一些稍微简单的像下面工作正常,但:

fileContent1 = Enumerator("blah" getBytes)
fileContent2 = Enumerator("more blah" getBytes)

SimpleResult(
  header = ResponseHeader(200),
  body = fileContent1 andThen fileContent2
)

什么我收到错了吗?

Answer 1:

我有最本从通过游戏代码,所以我可能误会了阅读,但是从我所看到的:在Enumerator.fromFile功能(Iteratee.scala [文件] [来源] )创建时应用到一个枚举Iteratee[Byte, Byte]追加一个Input.EOF到Iteratee的输出,当它完成从文件中读取。

根据播放! 你链接到您的文档例如得在枚举结束手动添加一个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

此修复程序,虽然我没有试过尚未将要走几级更深,使用Enumerator.fromCallback直接功能,通过它,保持返回一个自定义的猎犬功能Array[Byte] s,至所有你想要的文件拼接已经阅读。 请参阅实施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())})
}


Answer 2:

这是该剧框架2.2的代码,我使用的一起玩了一个又一个一堆音频文件。 你可以看到使用斯卡拉的Iterator是被转换成Java Enumerationjava.io.SequenceInputStream

def get_files(name: String) = Action { implicit request =>
  import java.lang.IllegalArgumentException
  import java.io.FileNotFoundException
  import scala.collection.JavaConverters._
  try {
    val file1 = new java.io.File("songs/phone-incoming-call.ogg")
    val file2 = new java.io.File("songs/message.ogg")
    val file3 = new java.io.File("songs/desktop-login.ogg")
    val inputStream1 = new java.io.FileInputStream(file1)
    val inputStream2 = new java.io.FileInputStream(file2)
    val inputStream3 = new java.io.FileInputStream(file3)
    val it = Iterator(inputStream1, inputStream2, inputStream3)
    val seq = new java.io.SequenceInputStream(it.asJavaEnumeration)
    val fileContent: Enumerator[Array[Byte]] = Enumerator.fromStream(seq)
    val length: Long = file1.length + file2.length + file3.length
    SimpleResult(
      header = ResponseHeader(200, Map(CONTENT_LENGTH -> length.toString)),
      body = fileContent
    )
  }
  catch {
    case e: IllegalArgumentException =>
      BadRequest("Could not retrieve file. Error: " + e.getMessage)
    case e: FileNotFoundException =>
      BadRequest("Could not find file. Error: " + e.getMessage)
  }
}

我的代码的唯一问题(在我所期待的方面)是,它是一个流这意味着我不能恢复从以前的时间点播放即使我发送CONTENT_LENGTH 。 也许我计算错误的方式的总长度。

另一个问题与它是音频文件必须是同一类型(预期),相同数量的渠道和相同的采样率的(我花了一段时间才能找出),例如,所有的都必须OGG 44100Hz 2通道。



文章来源: Why am I Failing to combine Enumerators in SimpleResult body?