websocket由浅入深二

上一篇我们说了一下websocket的基本概念及简单案例,本篇是一个案例,传输文本类型的文件,可以稍微扩展成大文件上传

前端代码

<template>
  <div>
    连接地址: <input type="text" id="conn" placeholder="ws://tmp.server.com:port/socket" v-model="connAddress"/>
    <button v-on:click="click">连接</button>
    <div>
      <textarea v-model="msg"></textarea>
      <button v-on:click="webSocketSend">发送文本消息</button>
    </div>
    接收到的文本消息:
    <div>
      <textarea v-model="receive"></textarea>
    </div>
    <!--------------------发送文件---------------------------------------------------->
    <!--大文件上传的话,无非就是根据文件的大小进行切分,然后固定每次传输多少字节,然后再服务端进行合并,自己实现吧-->
    <div>
      <input type="file"   @change="webSocketSendFile"/>
    </div>
    <!--img 用来显示服务端发送的图片-->
    收到的图片:<img :src="img" alt="">
  </div>
</template>

<script>
  export default {
    name: 'websocket',
    data() {
      return {
        connAddress: 'ws://localhost:8081/socket',
        msg: '',
        webSocket: null,
        receive: '',
        img: '',
        file: ''
      }
    },
    created() {
      // this.initWebSocket();
    },
    destroyed() {
      this.webSocket.close() //离开路由之后断开websocket连接
    },
    methods: {
      click() {
        this.initWebSocket();
      },
      initWebSocket() {
        this.webSocket = new WebSocket(this.connAddress);
        this.webSocket.onopen = this.webSocketOnOpen();
        this.webSocket.onmessage = this.webSocketOnMessage;
        this.webSocket.onopen = this.webSocketOnOpen;
        this.webSocket.onerror = this.webSocketOnError;
        this.webSocket.onclose = this.webSocketClose;
      },
      webSocketOnOpen(event) { //连接建立之后执行send方法发送数据
        console.log('连接建立', event);
      },
      webSocketOnError(event) {//连接建立失败重连
        console.log('失败', event);
        this.initWebSocket();
      },
      webSocketOnMessage(event) { //数据接收
        //把 event 打印出来 看看里面都有什么东西
        console.log('数据接收', event);
        //如果是图片类型,则显示图片
        if (event.data instanceof Blob){
          const src = window.URL.createObjectURL(event.data);
          this.img = src;
        }else {//文本信息直接输出
          this.receive = event.data;
        }
      },
      webSocketClose(event) {  //关闭
        console.log('断开连接', event);
      },
      webSocketSend() {//数据发送
        console.log(this.msg)
        this.webSocket.send(this.msg);
      },
      webSocketSendFile(e) {//文件数据发送
        let files = e.target.files;
        console.log(files)
        let blob = files[0].slice(0, files[0].size);
        this.webSocket.send(blob);
      },
    }
  }
</script>

<style scoped>
  #conn {
    width: 30%;
  }
  textarea {
    width: 30%;
    height: 50px;
  }
</style>

后端代码

@Configuration
public class WebSocketConfig  implements ServletContextInitializer {
    /**
     * 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint
     * @return
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    @Override
    public void onStartup(ServletContext servletContext) {
        servletContext.addListener(WebAppRootListener.class);
        servletContext.setInitParameter("org.apache.tomcat.websocket.textBufferSize","51200000");
        servletContext.setInitParameter("org.apache.tomcat.websocket.binaryBufferSize","51200000");
    }
}
@ServerEndpoint("/socket")
@Component
@Slf4j
public class WebSocketEndpoint {

    public WebSocketEndpoint() {
        log.info("构造方法执行:" + this.hashCode());
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        log.info(" onOpen session=" + session.getId());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        log.info(session.getId() + ":关闭了");
    }

    /**
     * 收到客户端发送的字节消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onBinaryMessage(Session session, byte[] message) {
        log.info("onMessage session=" + session.getId() + " message =" + message.length);
        //群发消息
        //将流写入文件
        saveFileFromBytes(message);
        //文件写入成功,返回一个ok
        session.getAsyncRemote().sendText("文件上传ok");
        //向客户端写图片
        sendFile(session);
    }

    public boolean saveFileFromBytes(byte[] b) {
        //创建文件流对象
        FileOutputStream fstream = null;
        //从map中获取file对象
        File file = new File("E://" + this.hashCode() + ".png");
        //判断路径是否存在,不存在就创建
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        try {
            fstream = new FileOutputStream(file, true);
            fstream.write(b);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (fstream != null) {
                try {
                    fstream.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return true;
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onTextMessage(Session session, String message) {
        log.info("onMessage session=" + session.getId() + " message =" + message);
        session.getAsyncRemote().sendText("我是服务端:" + message);
    }

    private void sendFile(Session session) {
        byte[] array = null;
        try {
            InputStream resourceAsStream = new ClassPathResource("test.png").getInputStream();
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buf = new byte[1024];
            int numBytesRead = 0;
            while ((numBytesRead = resourceAsStream.read(buf)) != -1) {
                output.write(buf, 0, numBytesRead);
            }
            array = output.toByteArray();
            output.close();
            resourceAsStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        ByteBuffer data = ByteBuffer.wrap(array);
        session.getAsyncRemote().sendBinary(data);
    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("onError");
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值