问题
I have a simple app which asks a DB a question, and then serves returns some data as simple text. The 'plain/text' response happens to be in CSV format. It gets read in by another program (matlab, through webread), and then we 'do analysis'.
Now, it appears that the play framework has changed some settings. Whereas before this code;
def singleEventsMultipleRegions(peril: String, region: List[String]) = Action.async {
val theResult = db.run(filter(peril, region).result)
val intermediate = theResult.map(result => header + result.mkString("\r\n"))
intermediate.map( item => Ok(item))
Gave me back exactly what I wanted. Now, matlab gets cut off after about 10000 rows. If I view the result in a browser, it loads the entire response. Rather frustrating.
Sadly, i don't understand what's happening... does anyone know?
Secondly, could anyone point me in the direction of...
The 'native' strategy for serving data dynamically in CSV format? The simple way of doing this so that a client doesn't finish reading early?
Cheers, Simon
回答1:
I have a partial answer here;
def allPerilStream = Action {
val stream = db.stream(allPerilsTable.result)
val source = Source.fromPublisher(stream.mapResult(u => u.aPeril + "\n")).map(ByteString.apply)
Ok.sendEntity(HttpEntity.Streamed(source, None, Some("")))
}
Which nearly works... except that it doesn't contain the table headers.
Any ideas on how we could insert a header into such a stream?
So, the final conclusion is as follows. It looks like it's possible to create akka sources directly from futures (this took me ages!!!!!) to figure out. Once you know that,
def allPerilStream = Action {
val theResult = for(
result <- db.run(allPerilsTable.result)
) yield (
header +
result.mkString("\n")
)
val source = Source.fromFuture(theResult).map(ByteString.apply)
val entity = HttpEntity.Streamed(source, None, Some(""))
Ok.sendEntity(entity)
}
I hope is going to do the trick
来源:https://stackoverflow.com/questions/37418568/how-to-properly-serve-csv-data-with-play-framework