2016-07-08 2 views
5

스칼라를 사용하여 Play Framework 2.3.x를 사용하여 마이크로 서비스를 만들고 있습니다. (둘 다 초보자입니다.) 요청을 스트리밍 할 수있는 방법을 찾지 못했습니다. 신체. 간단한 변환 : 나는 내가 분석하고 다른 형식으로 렌더링 거대한 TSV 파일을 수신 할 수있는 엔드 포인트 /transform 필요Play Framework 스칼라 : 요청 몸체를 스트리밍하는 방법

: 여기

문제입니다. 문제는 내 컨트롤러의 모든 명령이 "너무 늦게"실행된다는 것입니다. 코드를 시작하기 전에 전체 파일을 받기를 기다립니다.

예 :

나는 파일이 완전히 수신 할 때까지 기다릴 필요없이 요청 본문의 업로드 및 과정을 이미 요청시 라인 별을 읽을 수 있도록하려면
def transform = Action.async { 
    Future { 
     Logger.info("Too late") 
     Ok("A response") 
    } 
    } 

.

어떤 힌트라도 환영합니다.

+0

요청 본문을 multipart-form-data로 구문 분석하십시오. 문제가 해결 될지도 모릅니다. – Abhi

답변

8

이 답변은 해당 버전에서 Play의 Iteratee 기반 스트리밍을 대체하는 Akka 스트림 API를 사용하므로 Play 2.5.x 이상에 적용됩니다.

기본적으로 Ok.chunked(...)으로 전달할 수있는 Source[T]을 반환하는 본문 파서를 만들 수 있습니다. 이를 수행하는 한 가지 방법은 본문 파서에 Accumulator.source[T]을 사용하는 것입니다. 예를 들어, 단지 반환 된 데이터가 그대로 그것을 전송 작업은 다음과 같습니다

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) 
} 

을 원본, 예를 들면 변환하는 당신이 Flow를 사용할 수있는 TSV 파일을 변환과 같은 작업을 수행하려면 다음

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") 
} 

Play 문서의 Directing the Body Elsewhere 섹션에 더 많은 영감이있을 수 있습니다.

+0

감사! 이미 Play 2.3.x에서 작업하고 싶은 것들을 만드는 것이 문제라고 생각했습니다. 하지만 아마 2.5.x에서 재미로 이것을 시도 할 것입니다. – Cecile

관련 문제