akka-httpは、multipart/form-dataエンコーディングを使用してアップロードされたファイルをSource[ByteString, Any]
。 Java InputStream
を期待するライブラリを使用して非整列化する必要があります。
どうやって Source[ByteString, Any]
はInputStream
に変換できますか?
バージョン2.xでは、次のコードでこれを実現しています。
import akka.stream.scaladsl.StreamConverters
...
val inputStream: InputStream = entity.dataBytes
.runWith(
StreamConverters.asInputStream(FiniteDuration(3, TimeUnit.SECONDS))
)
注:バージョン2.0.2で壊れ、2.4.2で修正されました
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
}
}
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)