websocket实现web上传文件进度条

硅谷探秘者 7715 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

测试结束



评论区
请写下您的评论...
暂无评论...
猜你喜欢
工具 1911 服务端(接受) /** *接口 *@paramtype *@return */ @RequestMapping(value="/upFile",method
nginx,前端,java基础 1303   基于javanio+netty+websocket+protobuf+javascript等技术前后端高性能时数据输的demo模型。  github地址:https
框架 2013 springboot与回显资源映射路径配置:packagecom.dzqc.yx.controller
minio 2262 创建buckets 创建serviceaccounts java maven依赖: dependency groupIdio.minio/groupId
official 1030   基于javanio+netty+websocket+protobuf+javascript等技术前后端高性能时数据输的demo模型。  github地址:https
框架 2754 $FileSizeLimitExceededException:Thefieldfileexceedsitsmaximumpermittedsizeof1048576bytes.yml加配置springboot2.0配置spring:servlet:multipart:max-file-s
linux系统 1556 nginx代理报413(RequestEntityTooLarge)错误的解决方案RequestEntityTooLarge:请求的体太大,nginx代理时默认的大小是1M解决方案:设置
工具 2442 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 2023-06  3 2023-07  4 2023-08  1 2023-10  1 2024-02  1 2024-03  1 2024-04  1
标签
算法基础 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 javascript
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。