websocket实现web上传文件进度条
上次我们说了spring集成websocket,实现用websocket通讯
集成配置连接:http://www.jiajiajia.club/weblog/blog/artical/128
下面来模拟一次实现上传文件的进度条
原理:在上传文件之前,请求以下服务器,获取一个socketId(作用:用来标识本次连接,服务器端也是通过这个id找到对应的连接,然后给这个连接发送消息(进度)),此时socketId已经被保存在服务器的session中(作用:服务器发送消息的时候从session中获取socketId),客户端浏览器获取这个socketId以后,开始连接,连接时把获取的socketId当作参数带入,服务器会判断这个连接是否合法,或者是是否已经有这个id的连接,保证服务器发送消息的准确性。等websocket连接成功以后,就可以进行上传文件等操作,服务器端可以通过保存在session中的socketId向客户端浏览器发送数据。
1.首先对websocket处理器进行改进
package com.dzqc.dz.common.controller;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
/**
* websocket处理器
* @author LENOVO
*/
public class WebSocketHandler extends TextWebSocketHandler {
public static Map<String,WebSocketSession> map=new HashMap<String,WebSocketSession>();
private String id;
//连接建立后处理
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
String id=(String) session.getAttributes().get("socketId");
this.id=id;
System.out.println(id+":建立链接");
if(!map.containsKey(id)) {
map.put(id, session);
}else {
session.close();
}
super.afterConnectionEstablished(session);
}
//抛出异常时处理
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if(session.isOpen()){
session.close();
if(map.containsKey(this.id)) {
map.remove(this.id);
}
}
}
//连接关闭后处理
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
try {
if(map.containsKey(this.id)) {
map.remove(this.id);
}
session.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//接收文本消息,并发送出去
@Override
protected void handleTextMessage(WebSocketSession session,TextMessage message) throws Exception {
return ;
}
public static boolean sendMessage(String id,String message) {
if(map.containsKey(id)) {
WebSocketSession session=map.get(id);
try {
session.sendMessage(new TextMessage(message));
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}else {
return false;
}
}
/**
* 关闭指定连接
* @param socketId
* @return
*/
public static boolean closeSocket(String socketId) {
if(map.containsKey(socketId)) {
WebSocketSession w=map.get(socketId);
if(w.isOpen()) {
try {
w.close();
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}else {
return false;
}
}else {
return false;
}
}
}
2.模拟获取socketId,以及发送数据的controller
package com.dzqc.dz.common.controller;
import java.util.UUID;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.dzqc.dz.common.util.MyAjaxResult;
@Controller
@RequestMapping("/test")
public class TestControllers {
/**
* 跳转页面
* @param session
* @param id
* @return
*/
@RequestMapping("/test")
public String test(HttpSession session,String id) {
return "index2";
}
/**
* 获取标识socketId
* @param session
* @return
*/
@RequestMapping("/socketId")
@ResponseBody
public MyAjaxResult yanz(HttpSession session) {
String uid=UUID.randomUUID().toString();
session.setAttribute("socketId",uid);
return MyAjaxResult.success(uid);
}
/**
* 模拟发送信息
* @param session
* @return
*/
@RequestMapping("/send")
@ResponseBody
public String test(HttpSession session) {
String socketId=(String) session.getAttribute("socketId");
try {
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<100;i++){
boolean b=WebSocketHandler.sendMessage(socketId,i+"%");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
WebSocketHandler.closeSocket(socketId);
}
}).start();
} catch (Exception e) {
e.printStackTrace();
return "send error";
}
return "send success";
}
}
3.模拟进度条页面
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试</title>
</head>
<body>
<div>
测试 websocket<br>
<button id="up">开始上传</button><br>
进度<span id="jindu">0%</span>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function(){
var uid;
$("#up").click(function(){
//请求socketId
$.ajax({
url:'${path}/test/socketId',
dataType:'json',
type:'get',
success:function(res){
uid=res.msg;
//请求成功以后 与服务器建立 ws协议 连接
var ws;
if ('WebSocket' in window) {
ws = new WebSocket("ws://"+window.location.host+"${pageContext.request.contextPath}/socket.do?type="+uid);
} else {
ws = new SockJS("http://"+window.location.host+"${pageContext.request.contextPath}/socket/info?type="+uid);
}
ws.onopen = function (evnt) {
console.log("websocket连接成功");
send();
};
ws.onmessage = function (evnt) {
console.log("进度:"+evnt.data);
$("#jindu").html(evnt.data);
};
ws.onerror = function (evnt) {
send();
console.log("连接失败");
$("#jindu").html("100%");
};
ws.onclose = function (evnt) {
console.log("关闭连接");
$("#jindu").html("100%");
}
}
})
//发送数据
function send(){
$.ajax({
url:'${path}/test/send',
dataType:'json',
type:'get',
success:function(res){
console.log(res);
}
})
}
})
})
</script>
</body>
</html>
4.测试
开始之前
连接成功:上传中
上传完成:关闭连接
测试结束
猜你喜欢
blog
java HttpClients上传文件
工具
1505
服务端(接受文件) /** *上传文件接口 *@paramtype *@return */ @RequestMapping(value="/upFile",method
nginx,前端,java基础
751
基于javanio+netty+websocket+protobuf+javascript等技术实现前后端高性能实时数据传输的demo模型。 github地址:https
blog
springboot上传文件与回显
框架
1745
springboot上传文件与回显资源映射路径配置:packagecom.dzqc.yx.controller
blog
java使用minio上传文件
minio
1483
创建buckets
创建serviceaccounts
java上传文件
maven依赖:
dependency
groupIdio.minio/groupId
official
633
基于javanio+netty+websocket+protobuf+javascript等技术实现前后端高性能实时数据传输的demo模型。 github地址:https
blog
springboot上传文件大小限制
框架
2445
$FileSizeLimitExceededException:Thefieldfileexceedsitsmaximumpermittedsizeof1048576bytes.yml文件加配置springboot2.0配置spring:servlet:multipart:max-file-s
linux系统
1249
nginx代理上传文件报413(RequestEntityTooLarge)错误的解决方案RequestEntityTooLarge:请求的实体太大,nginx代理时默认的大小是1M解决方案:设置
blog
java使用FTP上传文件
工具
2103
pom依赖dependencygroupIdcommons-net/groupIdartifactIdcommons-net/artifactIdversion3.6/version/dependencyFTP服务类packageclub.jiajiajia.bulider.service;importjava.io.IOException;importjava.io.InputStream;im
归档
2018年11月
12
2018年12月
33
2019年01月
28
2019年02月
28
2019年03月
32
2019年04月
27
2019年05月
33
2019年06月
6
2019年07月
12
2019年08月
12
2019年09月
21
2019年10月
8
2019年11月
15
2019年12月
25
2020年01月
9
2020年02月
5
2020年03月
16
2020年04月
4
2020年06月
1
2020年07月
7
2020年08月
13
2020年09月
9
2020年10月
5
2020年12月
3
2021年01月
1
2021年02月
5
2021年03月
7
2021年04月
4
2021年05月
4
2021年06月
1
2021年07月
7
2021年08月
2
2021年09月
8
2021年10月
9
2021年11月
16
2021年12月
14
2022年01月
7
2022年05月
1
2022年08月
3
2022年09月
2
2022年10月
2
2022年12月
5
2023年01月
3
2023年02月
1
2023年03月
4
2023年04月
2
标签
算法基础
linux
前端
c++
数据结构
框架
数据库
计算机基础
储备知识
java基础
ASM
其他
深入理解java虚拟机
nginx
git
消息中间件
搜索
maven
redis
docker
dubbo
vue
导入导出
软件使用
idea插件
协议
无聊的知识
jenkins
springboot
mqtt协议
keepalived
minio
mysql
ensp
网络基础
xxl-job
rabbitmq
haproxy
srs
音视频
webrtc
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。