akka-http は、multipart/form-data エンコーディングを使用してアップロードされたファイルを として表しますSource[ByteString, Any]
。を期待する Java ライブラリを使用して非整列化する必要がありInputStream
ます。
どのようSource[ByteString, Any]
にに変えることができますInputStream
か?
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)