Scala 将CSV文件流式传输到Spray中的浏览器

Scala 将CSV文件流式传输到Spray中的浏览器,scala,csv,spray,Scala,Csv,Spray,在我的应用程序的一部分中,我必须将CSV文件发送回浏览器。我有一个actor,它用一个Stream[String]回复,流的每个元素都是文件中应该发送给用户的一行 这就是我现在拥有的。请注意,我当前返回的是MediaType text/plain,用于调试目的,最终版本中为text/csv: trait TripService extends HttpService with Matchers

在我的应用程序的一部分中,我必须将CSV文件发送回浏览器。我有一个actor,它用一个Stream[String]回复,流的每个元素都是文件中应该发送给用户的一行

这就是我现在拥有的。请注意,我当前返回的是
MediaType text/plain
,用于调试目的,最终版本中为
text/csv

trait TripService extends HttpService
                          with Matchers
                          with CSVTripDefinitions {
  implicit def actorRefFactory: ActorRefFactory

  implicit val executionContext = actorRefFactory.dispatcher

  lazy val csvActor = Ridespark.system.actorSelection(s"/user/listeners/csv").resolveOne()(1000)

  implicit val stringStreamMarshaller = Marshaller.of[Stream[String]](MediaTypes.`text/plain`) { (v, ct, ctx) =>
    ctx.marshalTo(HttpEntity(ct, v.mkString("\n")))
  }

  val route = {
    get {
          path("trips" / Segment / DateSegment) { (network, date) =>
            respondWithMediaType(MediaTypes.`text/plain`) {
                                                            complete(askTripActor(date, network))
                                                          }
                                                }
        }
  }

  def askTripActor(date: LocalDate, network: String)
                  (implicit timeout: Timeout = Timeout(1000, TimeUnit.MILLISECONDS)): Future[Stream[String]] = {
    csvActor flatMap { actor => (actor ? GetTripsForDate(date, Some(network))).mapTo[Stream[String]] }
  }
}

class TripApi(info: AuthInfo)(implicit val actorRefFactory: ActorRefFactory) extends TripService

我的问题是它会将整个CSV加载到内存中(由于
stringStreamMarshaller
中的
mkString
)。有没有办法不这样做,即在生成CSV行时对其进行流式处理?

您不需要
stringStreamMarshaller
。使用内置的流封送拆收器应该已经完成了所需的操作,而无需添加额外的换行符。但是,添加换行符应该不会比使用
streamOfStrings.map(+“\n”)更困难
或者在csv actor中渲染行时,首先添加换行符。

您应该尝试在spray中使用分块响应:据我所知,更好的方法是从磁盘读取整个文件,因为它的界面很慢,并提供服务。如果你有SeloiOS提出为什么不这样做,那么你应该考虑某种流读取器,但它会挂起阅读演员。CSV不是从磁盘上的文件。我从系统的其他部分获取数据,并动态生成CSV以发送给客户端。我来看看分块的回答。谢谢您不需要
stringStreamMarshaller
。使用内置的流封送拆收器应该已经完成了所需的操作,而无需添加额外的换行符。但是,添加换行符应该不会比使用
streamOfStrings.map(+“\n”)
或只是在csv角色中渲染行时添加换行符更困难。@jrudolph:很抱歉,回复时间太长,我一直很忙。你的回答很有效!我不知道为什么在某个时候流编组器不起作用,但现在它起作用了。你能把你的评论改写成这个问题的答案吗?这样我就可以标记它了?