Playframework 在akka stream中使用源代码两次

Playframework 在akka stream中使用源代码两次,playframework,streaming,akka-stream,Playframework,Streaming,Akka Stream,我正在为我构建的web应用程序使用Play框架。Play 2.5使用Akka Stream API来允许请求/响应流 我有一个端点,传入的文件直接流式传输到Google Drive 我定义了一个如下所示的BodyParser: BodyParser("toDrive") { request => Accumulator.source[ByteString].mapFuture { source => Future.successful(Right("Done")) }

我正在为我构建的web应用程序使用Play框架。Play 2.5使用Akka Stream API来允许请求/响应流

我有一个端点,传入的文件直接流式传输到Google Drive

我定义了一个如下所示的
BodyParser

BodyParser("toDrive") { request =>
  Accumulator.source[ByteString].mapFuture { source =>
    Future.successful(Right("Done"))
  }
}
我使用源代码(
source[ByteString,]
)并将其馈送到我与Play提供的
WSClient
一起使用的
StreamedBody

我想使用给定的
源代码
,并使用
WSClient
进行两个不同的HTTP调用

我尝试了这种天真的方法,将相同的
源代码
传递到两个不同的
WSClient
调用中,但失败了。我认为解决我问题的办法是广播

我想从源代码中得到什么来创建两个源代码,供我的
WSClient
使用

我还在玩
Source
Flow
Sink
。我正试图弄明白这一切。

我想
.alsoTo()
源代码的方法就是你想要的。内部只是广播。

更新的解决方案:

  Accumulator[ByteString, Either[Result, String]] {
    val s1 = Sink
      .asPublisher[ByteString](fanout = false)
      .mapMaterializedValue(Source.fromPublisher)
      .mapMaterializedValue { source =>
        //do what you need with source
        Future.successful(Right("result 1"))
      }
    val s2 = Sink
      .asPublisher[ByteString](fanout = false)
      .mapMaterializedValue(Source.fromPublisher)
      .mapMaterializedValue { source =>
        //do what you need with source
        Future.successful(Right("result 2"))
      }

    def combine(val1: Future[Either[Result, String]],
                val2: Future[Either[Result, String]]): Future[Either[Result, String]] = {
      for {
        res1 <- val1
        res2 <- val2
      } yield {
        // do something with your result
        res1.right.flatMap(val1 => res2.right.map(val2 => val1 + val2))
      }
    }

    Sink.fromGraph(GraphDSL.create(s1, s2)(combine) { implicit b => (sink, sink2) =>
      import GraphDSL.Implicits._

      val broadcast = b.add(Broadcast[ByteString](2))

      broadcast ~> sink
      broadcast ~> sink2

      SinkShape(broadcast.in)
    })
  }
与我最初的方法相比,唯一有效的改变是我自己创建了
Sink
并允许
fanout
,这样我可以在两个不同的
WSClient
调用中使用源代码两次

你觉得专家怎么样

BodyParser("toDrive") { request =>
  def sourceToFut(src: Source): Future[T] = ???

  Accumulator[ByteString, Either[Result, T]] {
    Sink
      .asPublisher[ByteString](fanout = true)
      .mapMaterializedValue(Source.fromPublisher)
      .mapMaterializedValue { source =>
        val upload1Fut = sourceToFut(source)
        val upload2Fut = sourceToFut(source)
        for {
          file1 <- upload1Fut
          file2 <- upload2Fut
        } yield {
          (file1, file2)
        }
      }
  }
}