def fold[E, A](state: A)(f: (A, E) => A): Iteratee[E, A]
val userIteratee2 = Iteratee.fold(List[String]())((st, el:String) => st :+ el) //> userIteratee2 : play.api.libs.iteratee.Iteratee[String,List[String]] = Cont(<function1>)
(usersEnum |>>> userIteratee2).foreach {x => println(x)} //| List(Tiger, John, Jimmy, Kate, Chris)
val inputLength: Iteratee[String,Int] = { Iteratee.fold[String,Int](0) { (length, chars) => length + chars.length } //> inputLength : play.api.libs.iteratee.Iteratee[String,Int] = Cont(<function1>)
} Await.result((usersEnum |>>> inputLength),Duration.Inf) //> res1: Int = 23
val consume: Iteratee[String,String] = { Iteratee.fold[String,String]("") { (result, chunk) => result ++ chunk } //> consume : play.api.libs.iteratee.Iteratee[String,String] = Cont(<function1 >)
} Await.result((usersEnum |>>> consume),Duration.Inf) //> res2: String = TigerJohnJimmyKateChris
object ReactiveFileUpload extends Controller { def upload = Action(BodyParser(rh => new CsvIteratee(isFirst = true))) { request => Ok("File Processed") } } case class CsvIteratee(state: Symbol = 'Cont, input: Input[Array[Byte]] = Empty, lastChunk: String = "", isFirst: Boolean = false) extends Iteratee[Array[Byte], Either[Result, String]] {
def fold[B]( done: (Either[Result, String], Input[Array[Byte]]) => Promise[B], cont: (Input[Array[Byte]] => Iteratee[Array[Byte], Either[Result, String]]) => Promise[B], error: (String, Input[Array[Byte]]) => Promise[B] ): Promise[B] = state match { case 'Done =>
done(Right(lastChunk), Input.Empty) case 'Cont => cont(in => in match {
case in: El[Array[Byte]] => { // Retrieve the part that has not been processed in the previous chunk and copy it in front of the current chunk
val content = lastChunk + new String(in.e) val csvBody =
if (isFirst) // Skip http header if it is the first chunk
content.drop(content.indexOf("\r\n\r\n") + 4) else content val csv = new CSVReader(new StringReader(csvBody), ';') val lines = csv.readAll // Process all lines excepted the last one since it is cut by the chunk
for (line <- lines.init) processLine(line) // Put forward the part that has not been processed
val last = lines.last.toList.mkString(";") copy(input = in, lastChunk = last, isFirst = false) } case Empty => copy(input = in, isFirst = false) case EOF => copy(state = 'Done, input = in, isFirst = false)
case _ => copy(state = 'Error, input = in, isFirst = false)
}) case _ => error("Unexpected state", input) } def processLine(line: Array[String]) = WS.url("http://localhost:9200/affa/na/").post( toJson( Map( "date" -> toJson(line(0)), "trig" -> toJson(line(1)), "code" -> toJson(line(2)), "nbjours" -> toJson(line(3).toDouble) ) ) ) }