Как преобразовать Source [ByteString, Any] в InputStream
akka-http представляет файл, загруженный с использованием кодирования multipart/form-data как Source[ByteString, Any]
. Мне нужно размонтировать его с помощью библиотеки Java, которая ожидает InputStream
.
Как Source[ByteString, Any]
можно превратить в InputStream
?
Ответы
Ответ 1
Начиная с версии 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
Ответ 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
}
}
Ответ 3
Вы можете извлечь интернатор из ByteString, а затем получить InputStream. Что-то вроде этого (псевдокод):
source.map { data: ByteString =>
data.iterator.asInputStream
}
Обновление
Более подробный пример, начинающийся с Multipart.FormDatap >
def isSourceFromFormData(formData: Multipart.FormData): Source[InputStream, Any] =
formData.parts.map { part =>
part.entity.dataBytes
.map(_.iterator.asInputStream)
}.flatten(FlattenStrategy.concat)