akka 在Play 2.5中处理字节串和字符串的WebSocket

ulmd4ohb  于 2022-11-06  发布在  其他
关注(0)|答案(2)|浏览(192)

我是Play Framework和Scala的新手。我尝试在Play中使用websockets编写文件上传。我发现可以使用ByteString来完成。但我面临的问题是我无法将响应消息保持为String

def upload = WebSocket.accept[ByteString, String] { request =>
  ActorFlow.actorRef(out => UploadActor.props(out))
}

我得到的异常如下所示,

play.sbt.PlayExceptions$CompilationException: Compilation error[could not find implicit value for parameter transformer: play.api.mvc.WebSocket.MessageFlowTransformer[akka.util.ByteString,String]]
  at play.sbt.PlayExceptions$CompilationException$.apply(PlayExceptions.scala:27)
  at play.sbt.PlayExceptions$CompilationException$.apply(PlayExceptions.scala:27)
  at scala.Option.map(Option.scala:145)
  at play.sbt.run.PlayReload$$anonfun$taskFailureHandler$1.apply(PlayReload.scala:49)
  at play.sbt.run.PlayReload$$anonfun$taskFailureHandler$1.apply(PlayReload.scala:44)
  at scala.Option.map(Option.scala:145)
  at play.sbt.run.PlayReload$.taskFailureHandler(PlayReload.scala:44)
  at play.sbt.run.PlayReload$.compileFailure(PlayReload.scala:40)
  at play.sbt.run.PlayReload$$anonfun$compile$1.apply(PlayReload.scala:17)
  at play.sbt.run.PlayReload$$anonfun$compile$1.apply(PlayReload.scala:17)

处理WebSocket的执行元如下所示,

class UploadActor(out: ActorRef) extends Actor{
  out ! "Hello"

  def receive = {
    case msg: ByteString => {
      val p = new PrintWriter(new File("/tmp/newFile.mp4"))
      p.print(msg.asByteBuffer)
      p.flush()
      out ! "file received"
    }
    case msg: String => out ! ("Got it "+ msg)
  } 
}
tp5buhyn

tp5buhyn1#

Playframework WebSocket支持依赖于Akka Streams,因此将通用WebSocket消息流表示为MessageMessage类型的Flow。输入和输出参数的任何其他组合都需要以MessageFlowTransformer[In, Out]的形式隐式提供。
现在,Playframework提供了一些转换器-例如MessageFlowTransformer[String, String]MessageFlowTransformer[ByteString, ByteString]等。要查看完整的列表,请查看源代码。
如果你想把ByteString转换成String,你需要在作用域中提供你自己的转换器。

implicit val byteStringToStringMessageFlowTransformer: MessageFlowTransformer[ByteString, String] = {
      new MessageFlowTransformer[ByteString, String] {
        def transform(flow: Flow[ByteString, String, _]) = {
          AkkaStreams.bypassWith[Message, ByteString, Message](Flow[Message] collect {
            case BinaryMessage(data) => Left(data)
            case TextMessage(_) =>
              Right(CloseMessage(
                Some(CloseCodes.Unacceptable),
                "This WebSocket only supports binary frames"))
          })(flow map TextMessage.apply)
        }
      }
    }

更多信息请参阅docs

jm2pwxwz

jm2pwxwz2#

Scala WebSockets实际上已经完成了重构:
https://www.playframework.com/documentation/2.8.x/StreamsMigration25#Migrating-Scala-WebSockets
您现在可以使用play.api.http.websocket.Message来发送和接收各种类型的WebSocket帧:

WebSocket.accept[Message, Message] { request =>
  ActorFlow.actorRef { out =>
    WebSocketActor.props(out)
  }
}

请参阅the sealed trait Message以了解BinaryMessageTextMessage等。

相关问题