【问题标题】:Websocket to handle ByteString and String in Play 2.5Websocket 在 Play 2.5 中处理 ByteString 和 String
【发布时间】:2017-04-22 16:18:01
【问题描述】:

我是 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)
  } 
}

【问题讨论】:

    标签: scala playframework akka playframework-2.5


    【解决方案1】:

    Playframework WebSocket 支持依赖于 Akka Streams,因此将通用 WebSocket 消息流表示为类型为 MessageMessageFlow。输入和输出参数的任何其他组合都需要作为MessageFlowTransformer[In, Out] 隐式提供。

    现在,Playframework 提供了一些转换器 - 例如。 MessageFlowTransformer[String, String]MessageFlowTransformer[ByteString, ByteString] 等。完整列表请查看source code

    如果您希望 ByteStringString,您需要在范围内提供您自己的转换器。如下所示:

    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

    【讨论】:

    • 我已经将给定的代码放在了控制器中,但还是一样的异常。
    【解决方案2】:

    Play 2.5 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)
      }
    }
    

    BinaryMessageTextMessage 等请参见 the sealed trait Message

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-29
      相关资源
      最近更新 更多