websocket实现web上传文件进度条

硅谷探秘者 5883 0 0

上次我们说了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.测试

        开始之前

menu.saveimg.savepath20190301185807.jpg

        连接成功:上传中

menu.saveimg.savepath20190301185820.jpg

        上传完成:关闭连接

menu.saveimg.savepath20190301185847.jpg

测试结束


猜你喜欢
工具 1187 服务端(接受) /** *接口 *@paramtype *@return */ @RequestMapping(value="/upFile",method
nginx,前端,java基础 363   基于javanio+netty+websocket+protobuf+javascript等技术前后端高性能时数据输的demo模型。  github地址:https
框架 1487 springboot与回显资源映射路径配置:packagecom.dzqc.yx.controller
minio 254 创建buckets 创建serviceaccounts java maven依赖: dependency groupIdio.minio/groupId
official 308   基于javanio+netty+websocket+protobuf+javascript等技术前后端高性能时数据输的demo模型。  github地址:https
框架 2194 $FileSizeLimitExceededException:Thefieldfileexceedsitsmaximumpermittedsizeof1048576bytes.yml加配置springboot2.0配置spring:servlet:multipart:max-file-s
linux系统 979 nginx代理报413(RequestEntityTooLarge)错误的解决方案RequestEntityTooLarge:请求的体太大,nginx代理时默认的大小是1M解决方案:设置
前端(h5) 1720 后端这么写packagecn.com.dzqc.controller;importjavax.servlet.http.HttpServletRequest;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.RequestMapping;importorg.sp
归档
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
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议 无聊的知识 jenkins springboot mqtt协议 keepalived minio mysql ensp 网络基础
目录
余生别太较劲,放过自己 才会幸福。