微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

发送文件思想 Actix websocket

如何解决发送文件思想 Actix websocket

为了通过 websocket 发送文件,我很难找到文档或教程。 这是我的 JS:

['dragleave','drop'].forEach(event_name =>
document.addEventListener(event_name,function(e) {
  e.preventDefault();
  let files = e.dataTransfer.files;
  var reader = new FileReader();
  for(let i=0;i<files.length; i++) {
    reader.onload = function(event) {
      socket.send(event.target.result);
    };
    reader.readAsArrayBuffer(files[i]);
  }
  },false));

我的 Rust 代码基于官方示例 (https://github.com/actix/examples/tree/master/websockets/websocket):

impl StreamHandler<Result<ws::Message,ws::ProtocolError>> for RatIoUpWS {
    fn handle(&mut self,msg: Result<ws::Message,ws::ProtocolError>,ctx: &mut Self::Context,) {
        // process websocket messages
        println!("WS: {:?}",msg);
        match msg {
            Ok(ws::Message::Ping(msg)) => {
                self.hb = Instant::Now();
                ctx.pong(&msg);
            }
            Ok(ws::Message::Pong(_)) => {self.hb = Instant::Now();}
            Ok(ws::Message::Text(text)) => {
                ctx.text(text);
            }
            Ok(ws::Message::Binary(bin)) => {
                let mut pos = 0;
                let mut buffer = File::create("foo.txt").unwrap();  // notice the name of the file that will be written
                while pos < bin.len() {
                    let bytes_written = buffer.write(&bin[pos..]).unwrap();
                    pos += bytes_written
                };
                ctx.binary(bin)
            },Ok(ws::Message::Close(reason)) => {
                ctx.close(reason);
                ctx.stop();
            }
            _ => ctx.stop(),//if file>64K,it goes here
        }
    }
}

它似乎被识别为短信,我不知道如何反序列化它。 actix_web::web::Form<FormDataStruct> 似乎不合适。

有什么想法吗?

解决方法

您的 WebSocket 服务器将消息识别为文本,因为您的 JavaScript 代码使用 FormData() 而不是使用 ArrayBuffer 分派文本数据。

要使用 WebSocket 从浏览器传输文件,您可以使用以下示例代码(注意 WebSocket 声明和 sendFile() 函数):

    var ws;
    function connectToWS() {
      var wsUri = (window.location.protocol=='https:'&&'wss://'||'ws://')+window.location.host + '/ws/';
      console.log(wsUri);
      ws = new WebSocket(wsUri);
      ws.binaryType = "arraybuffer";  // Note the binaryType here
      ws.onopen = function() {alert("Connected.");};
      ws.onmessage = function(evt) {alert(evt.msg);};
      ws.onclose = function() {
        ws = null;
        alert("Connection is closed...");
      };
      ws.onerror = function(e) {alert(e.msg);}
    }

    function sendFile() {
      var file = document.getElementById('filename').files[0];
      var reader = new FileReader();
      var rawData = new ArrayBuffer();            
      reader.loadend = function() {}
      reader.onload = function(e) {
          rawData = e.target.result;
          ws.send(rawData);
          alert("the File has been transferred.")
      }
      reader.readAsArrayBuffer(file);
    }

要在服务器端处理传输的字节,您可以使用标准 Rust 库 (std::io::Write)。使用 std::io 更改您提供的相同示例 Rust 代码来处理 .txt 文件:

impl StreamHandler<Result<ws::Message,ws::ProtocolError>> for MyWebSocket {
    fn handle(
        &mut self,msg: Result<ws::Message,ws::ProtocolError>,ctx: &mut Self::Context,) {
        // process websocket messages
        println!("WS: {:?}",msg);
        match msg {
            Ok(ws::Message::Ping(msg)) => {
                self.hb = Instant::now();
                ctx.pong(&msg);
            }
            Ok(ws::Message::Pong(_)) => {
                self.hb = Instant::now();
            }
            Ok(ws::Message::Text(text)) => ctx.text(text),Ok(ws::Message::Binary(bin)) => {
                let mut pos = 0;
                let mut buffer = File::create("foo.txt").unwrap();  // notice the name of the file that will be written
                while pos < bin.len() {
                    let bytes_written = buffer.write(&bin[pos..]).unwrap();
                    pos += bytes_written
                };
                ctx.binary(bin)
            },Ok(ws::Message::Close(reason)) => {
                ctx.close(reason);
                ctx.stop();
            }
            _ => ctx.stop(),}
    }
}

您可以在此存储库中查看完整的工作示例:https://github.com/vnderlev/actix_ws_file_transfer(改编自 official actix/example repository)。

希望这个回答对您有所帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?