上一篇我们说了一下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");
}
}