简体   繁体   English

如何将Source [ByteString,Any]转换为InputStream

[英]How to convert Source[ByteString, Any] to InputStream

akka-http represents a file uploaded using multipart/form-data encoding as Source[ByteString, Any] . akka-http表示使用multipart / form-data编码作为Source[ByteString, Any]上传的文件。 I need to unmarshal it using Java library that expects an InputStream . 我需要使用需要InputStream Java库来解组它。

How Source[ByteString, Any] can be turned into an InputStream ? Source[ByteString, Any]如何变成InputStream

As of version 2.x you achieve this with the following code: 从版本2.x开始,您可以使用以下代码实现此目的:

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

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

Note: was broken in version 2.0.2 and fixed in 2.4.2 注意:在版本2.0.2中已中断,在2.4.2中已修复

You could try using an OutputStreamSink that writes to a PipedOutputStream and feed that into a PipedInputStream that your other code uses as its input stream. 您可以尝试使用OutputStreamSink写入PipedOutputStream并将其提供给PipedInputStream ,而其他代码将其用作其输入流。 It's a little rough of an idea but it could work. 这是一个有点粗略的想法,但它可以工作。 The code would look like this: 代码如下所示:

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
  }           
}

You could extract an interator from ByteString and then get the InputStream. 您可以从ByteString中提取一个interator,然后获取InputStream。 Something like this (pseudocode): 像这样的东西(伪代码):

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

Update 更新

A more elaborated sample starting with a Multipart.FormData 一个以Multipart.FormData开头的更详细的示例

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM