Play Framework和Scala的新手。我试图在播放中使用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的Actor如下,
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)
}
}
答案 0 :(得分:1)
Playframework WebSocket支持依赖于Akka Streams,因此表示一个通用的WebSocket消息流为Flow
类型Message
到Message
。输入和输出参数的任何其他组合都需要隐式提供为MessageFlowTransformer[In, Out]
。
现在,Playframework提供了一些变压器 - 例如MessageFlowTransformer[String, String]
,MessageFlowTransformer[ByteString, ByteString]
等。有关完整列表,请查看source code。
如果您希望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中的更多信息。
答案 1 :(得分:0)
Play 2.5 Scala WebSocket实际上已经进行了重构:
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)
}
}
有关BinaryMessage
,TextMessage
等,请参见the sealed trait Message。