gpt4 book ai didi

scala - 如何使用 Play 2.5 在分块响应中将 Anorm 大型查询结果流式传输到客户端

转载 作者:行者123 更新时间:2023-12-02 04:03:08 24 4
gpt4 key购买 nike

我有一个非常大的结果集(超过 60k 记录列),我从数据库中提取并使用 Anorm 进行解析(尽管我可以使用 play 的默认数据访问模块,该模块在需要时返回 ResultSet)。我需要将这些结果直接转换并流式传输到客户端(无需将它们保存在内存中的大列表中),然后将它们直接下载到客户端机器上的文件中。

我一直在引用 ScalaStream 2.5.x 中分块响应部分所展示的内容。播放文档。我无法实现它在那里显示的“getDataStream”部分。

我还引用了 ScalaAnorm 2.5.x 的 Streaming Results 和 Iteratee 部分演示的内容。播放文档。我已经尝试将结果作为枚举器进行管道传输,就像这里返回的一样:

 val resultsEnumerator = Iteratees.from(SQL"SELECT * FROM Test", SqlParser.str("colName"))

进入

val dataContent = Source.fromPublisher(Streams.enumeratorToPublisher(resultsEnumerator))
Ok.chunked(dataContent).withHeaders(("ContentType","application/x-download"),("Content-disposition","attachment; filename=myDataFile.csv"))

但是生成的文件/内容是空的。

而且我找不到任何关于如何在数据服务中转换返回如下内容的函数的示例代码或引用:

@annotation.tailrec
def go(c: Option[Cursor], l: List[String]): List[String] = c match {
case Some(cursor) => {
if (l.size == 10000000) l // custom limit, partial processing
else {
go(cursor.next, l :+ cursor.row[String]("VBU_NUM"))
}
}
case _ => l
}

val sqlString = s"select colName FROM ${tableName} WHERE ${whereClauseStr}"

val results : Either[List[Throwable], List[String]] = SQL(sqlString).withResult(go(_, List.empty[String]))
results

变成我可以传递给 Ok.chunked() 的东西。

所以基本上我的问题是,我应该如何将每个从数据库中获取的记录提供给一个流,我可以对其进行转换并作为可以下载到文件的分块响应发送给客户端?

我不想为此使用 Slick。但我可以采用不使用 Anorm 的解决方案,只使用返回原始 java.sql.ResultSet 对象的 play dbApi 对象并使用它。

最佳答案

在引用 Anorm Akka Support 之后文档和多次试验和错误,我能够实现我想要的解决方案。我必须添加这些依赖项

"com.typesafe.play" % "anorm_2.11" % "2.5.2",
"com.typesafe.play" % "anorm-akka_2.11" % "2.5.2",
"com.typesafe.akka" %% "akka-stream" % "2.4.4"

通过 Play 2.5 的 build.sbt 文件。

我实现了这样的东西

//...play imports
import anorm.SqlParser._
import anorm._

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Sink, Source}

...

private implicit val akkaActorSystem = ActorSystem("MyAkkaActorSytem")
private implicit val materializer = ActorMaterializer()

def streamedAnormResultResponse() = Action {
implicit val connection = db.getConnection()

val parser: RowParser[...] = ...
val sqlQuery: SqlQuery = SQL("SELECT * FROM table")

val source: Source[Map[String, Any] = AkkaStream.source(sqlQuery, parser, ColumnAliaser.empty).alsoTo(Sink.onComplete({
case Success(v) =>
connection.close()
case Failure(e) =>
println("Info from the exception: " + e.getMessage)
connection.close()
}))

Ok.chunked(source)
}

关于scala - 如何使用 Play 2.5 在分块响应中将 Anorm 大型查询结果流式传输到客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40944093/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com