web-dev-qa-db-ja.com

Source [ByteString、Any]をInputStreamに変換する方法

akka-httpは、multipart/form-dataエンコーディングを使用してアップロードされたファイルをSource[ByteString, Any]。 Java InputStreamを期待するライブラリを使用して非整列化する必要があります。

どうやって Source[ByteString, Any]InputStreamに変換できますか?

30
kostya

バージョン2.xでは、次のコードでこれを実現しています。

import akka.stream.scaladsl.StreamConverters
...
val inputStream: InputStream = entity.dataBytes
        .runWith(
           StreamConverters.asInputStream(FiniteDuration(3, TimeUnit.SECONDS))
        )

参照: http://doc.akka.io/docs/akka-stream-and-http-experimental/2.0.1/scala/migration-guide-1.0-2.x-scala.html

注:バージョン2.0.2で壊れ、2.4.2で修正されました

23
Bennie Krijger

OutputStreamSinkに書き込むPipedOutputStreamを使用してみて、他のコードが入力ストリームとして使用するPipedInputStreamにフィードすることができます。それは少し大まかなアイデアですが、うまくいく可能性があります。コードは次のようになります。

import akka.util.ByteString
import akka.stream.scaladsl.Source
import Java.io.PipedInputStream
import Java.io.PipedOutputStream
import akka.stream.io.OutputStreamSink
import Java.io.BufferedReader
import Java.io.InputStreamReader
import akka.actor.ActorSystem
import akka.stream.ActorFlowMaterializer

object PipedStream extends App{
  implicit val system = ActorSystem("flowtest")
  implicit val mater = ActorFlowMaterializer()

  val lines = for(i <- 1 to 100) yield ByteString(s"This is line $i\n")
  val source = Source(lines)

  val pipedIn = new PipedInputStream()
  val pipedOut = new PipedOutputStream(pipedIn)      
  val flow = source.to(OutputStreamSink(() => pipedOut))
  flow.run()

  val reader = new BufferedReader(new InputStreamReader(pipedIn))
  var line:String = reader.readLine
  while(line != null){
    println(s"Reader received line: $line")
    line = reader.readLine
  }           
}
7
cmbaxter

ByteStringからインタレーターを抽出してから、InputStreamを取得できます。次のようなもの(擬似コード):

source.map { data: ByteString =>
  data.iterator.asInputStream
}

更新

Multipart.FormDataで始まるより詳細なサンプル

def isSourceFromFormData(formData: Multipart.FormData): Source[InputStream, Any] = 
 formData.parts.map { part => 
   part.entity.dataBytes
   .map(_.iterator.asInputStream)
}.flatten(FlattenStrategy.concat)