Iteratee用于流数据上传

时间:2014-07-02 03:32:20

标签: scala playframework

发布this帖后,使用自定义解析器/ Iteratee实现基于流的文件上传。当然,该帖子中的代码是旧的,不再编译。以下是我正在尝试的。

case class UploadIteratee(state: Symbol = 'Cont, input: Input[Array[Byte]] = Empty, received: Int = 0) extends Iteratee[Array[Byte], Either[Result, Int]] {
def fold[B](folder: Step[Array[Byte], Either[Result, Int]] => Future[B])(implicit ec: ExecutionContext): Future[B] = {
  folder(
    Step.Cont(in => in match {
      case in: El[Array[Byte]] => copy(input = in, received = received + in.e.length)
      case Empty => copy(input = in)
      case EOF => copy(state = 'Done, input = in)
      case _ => copy(state = 'Error, input = in)
    }))
}
}

def send = Action(BodyParser(rh => new UploadIteratee).map(Right(_))) { request =>
Ok("Done")

}

这看起来是否正确且足以接受来自文件上传的流?我必须做一些愚蠢的事情才能得到以下编译错误。

type mismatch; found : controllers.MyController.UploadIteratee required: 
 play.api.libs.iteratee.Iteratee[Array[Byte],Either[play.api.mvc.SimpleResult,?]]

修改 我在Play 2.2.2。我很糟糕,我正在看2.3源代码。现在跟随编译

case class UploadIteratee(state: Symbol = 'Cont, input: Input[Array[Byte]] = Empty, received: Int = 0) extends Iteratee[Array[Byte], Either[SimpleResult, Int]] {
def fold[B](folder: Step[Array[Byte], Either[SimpleResult, Int]] => Future[B])(implicit ec: ExecutionContext): Future[B] = {
  folder(
    Step.Cont(in => in match {
      case in: El[Array[Byte]] => copy(input = in, received = received + in.e.length)
      case Empty => copy(input = in)
      case EOF => copy(state = 'Done, input = in)
      case _ => copy(state = 'Error, input = in)
    }))
}
}
def send = Action(BodyParser(rh => new UploadIteratee).map(Right(_))) { request =>
 Ok("Done")
}

wingedsubmariner:我正在尝试编写一个主体解析器,它接收文件上传功能的数据流。随后,我将不得不在流中收到的每条记录中填充另一个数据保存案例类。我对Iteratee的理解仍然是原始的,所以任何指针都会受到赞赏。

1 个答案:

答案 0 :(得分:-1)

无需为大多数任务编写自定义Iteratee实现。而是使用Iteratee的伴随对象中的工厂方法。在这种情况下,我们可以使用Iteratee.foreach创建一个正文解析器,在收到每个数据块时执行某些操作:

val bodyParser = BodyParser { requestHeader =>
  Iteratee.foreach[Array[Byte]] { block =>
    // Do something with each block as it is received
  }.map(Right(_))
}

更复杂的实现可能会使用Enumeratee将传入的字节流分解为不同的记录,然后由Iteratee使用。