Ta odpowiedź dotyczy gry w wersji 2.5.x i nowszej, ponieważ korzysta z interfejsu API strumieni Akka, który zastąpił strumieniowanie oparte na Iteratee Play w tej wersji.
Zasadniczo można utworzyć analizator treści, który zwraca wartość Source[T]
, którą można przekazać do Ok.chunked(...)
. Jednym ze sposobów na to jest użycie Accumulator.source[T]
w analizatorze treści. Na przykład, działanie, które właśnie wrócił dane wysyłane do niego verbatim może wyglądać następująco:
def verbatimBodyParser: BodyParser[Source[ByteString, _]] = BodyParser { _ =>
// Return the source directly. We need to return
// an Accumulator[Either[Result, T]], so if we were
// handling any errors we could map to something like
// a Left(BadRequest("error")). Since we're not
// we just wrap the source in a Right(...)
Accumulator.source[ByteString]
.map(Right.apply)
}
def stream = Action(verbatimBodyParser) { implicit request =>
Ok.chunked(request.body)
}
Jeśli chcesz zrobić coś takiego przekształcenia pliku TSV można użyć Flow
przekształcić źródła, np
val tsvToCsv: BodyParser[Source[ByteString, _]] = BodyParser { req =>
val transformFlow: Flow[ByteString, ByteString, NotUsed] = Flow[ByteString]
// Chunk incoming bytes by newlines, truncating them if the lines
// are longer than 1000 bytes...
.via(Framing.delimiter(ByteString("\n"), 1000, allowTruncation = true))
// Replace tabs by commas. This is just a silly example and
// you could obviously do something more clever here...
.map(s => ByteString(s.utf8String.split('\t').mkString(",") + "\n"))
Accumulator.source[ByteString]
.map(_.via(transformFlow))
.map(Right.apply)
}
def convert = Action(tsvToCsv) { implicit request =>
Ok.chunked(request.body).as("text/csv")
}
Może być więcej inspiracji w sekcji Directing the Body Elsewhere w dokumentach Play.
przeanalizować treść żądania jako wieloczęściowe dane formularza. Może to rozwiązać twój problem. – Abhi