栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot整合websocket(三)上传文件(终篇)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot整合websocket(三)上传文件(终篇)

springboot整合websocket(三)上传文件(终篇)

springboot整合websocket(一)简单聊天室
springboot整合websocket(二)上传文件(引导篇)
springboot整合websocket(三)上传文件(终篇)


说明

这里就涉及到一个问题,文件保存在服务器,前端页面要等后端保存完了之后,再发送下一份。

而前端想要接收服务器的消息,只能在OnMessage,所以我们需要改3个地方

  1. 前端webSocket.onmessage()方法里面,我们需要判断一下,哪些消息是显示的,哪些消息是发送下一份文件
  • 这个采用的就是Message类将消息封装,转成json后发给前端,前端拿到json后在转成对象
  1. 前端发送文件的时候,我们需要保存文件的上传进度,以便发下一份文件的时候,我们可以发送正确的部分
  • 文件切割用的是slice()方法,具体在js的sendFile(addSize)
  1. 服务器onMessage(byte[]),需要给前端发送一个消息,告诉前端发送下一部分文件

直接上代码

这里我使用了Gson,放一下依赖



  com.google.code.gson
  gson

服务器端
@Log4j2
@Controller
@ServerEndpoint("/websocket")
public class baseWebsocketController
{

    //使用 ConcurrentHashMap, 保证线程安全, static全局共享 session

    //这里之所以static,是因为这个类不是单例的!!
    //他虽然有@Controller注解,但是不适用Ioc容器中拿对象,每一次请求过来都是一个新的对象

    //存放 session
    private final static Map sessions = new ConcurrentHashMap<>();

    private final static Gson gson = new Gson();

    //onopen 在连接创建(用户进入聊天室)时触发
    @OnOpen
    public void openSession(Session session, EndpointConfig config)
    {
        //将session存起来, 用于服务器向浏览器发送消息
        sessions.put(session.getId(), session);
        sendAll("msg", "[" + session.getId() + "]进入房间");
    }

    //响应字符串
    @OnMessage
    public void onMessage(Session session, String message) throws Exception
    {
        // session.getUserProperties() 是一个 Map, 用于存放数据
        session.getUserProperties().put("filename", message);
        //这里处理一下, 如果有该文件, 就先删除
        File file = new File(getProjectRootPath(), message);
        if (file.exists()) {
            file.delete();
        }
        //输出一下文件路径
        System.out.println(file.getCanonicalPath());
    }

    //响应字节流
    @OnMessage
    public void onMessage(Session session, byte[] message)
    {
        // 1、先拿到文件名
        final String filename = (String) session.getUserProperties().get("filename");
        // 2、追加到该文件
        File file = new File(getProjectRootPath(), filename);

        try (OutputStream os = new FileOutputStream(file, true)) {
            os.write(message, 0, message.length);
        }
        catch (IOException e) {
            e.printStackTrace();
        }

        //返回已经上传的字节数
        send(session, "file", message.length + "");
    }

    //onclose 在连接断开(用户离开聊天室)时触发
    @OnClose
    public void closeSession(Session session, CloseReason closeReason)
    {
        //记得移除相对应的session
        sessions.remove(session.getId());

        //打印一下原因
        System.out.println(closeReason.getReasonPhrase());

        sendAll("msg", "[" + session.getId() + "]离开了房间");
    }

    @OnError
    public void sessionError(Session session, Throwable throwable)
    {
        throwable.printStackTrace();
        //通常有异常会关闭session
        try {
            session.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void sendAll(String tip, String message)
    {
        //使用Message封装
        Message msg = new Message(tip, message);
        //用gson转成json字符串
        final String msgStr = gson.toJson(msg);

        for (Session s : sessions.values()) {
            //获得session发送消息的对象
            //Basic是同步, 会阻塞
            //Async是异步, 这个会有多线程并发导致异常, 发送消息太快也会有并发异常, 需要有 消息队列 来辅助使用
            final RemoteEndpoint.Basic remote = s.getBasicRemote();
            try {
                //发送消息
                remote.sendText(msgStr);
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void send(Session session, String tip, String message)
    {
        //使用Message封装
        Message msg = new Message(tip, message);
        //用gson转成json字符串
        final String msgStr = gson.toJson(msg);

        final RemoteEndpoint.Basic remote = session.getBasicRemote();
        try {
            //发送消息
            remote.sendText(msgStr);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    
    private String getProjectRootPath()
    {
        try {
            String path = ResourceUtils.getURL(ResourceUtils.CLASSPATH_URL_PREFIX).getPath();
            path = URLDecoder.decode(path, "UTF-8");
            final File file = new File(path, "static");
            return file.getCanonicalPath();
        }
        catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    private static class Message
    {
        private String tip;
        private String msg;
    }
}



页面



  
  websocket-demo
  
  


  


End


Question 1

Q:我又想发消息又想上传文件怎么办
A:
1、在js里面也封装一个对象,将json传给后
2、后端收到json后,转成对象,判断是发消息,还是发送的文件名就ok啦

Question 2

Q:我想选择很多个文件咋办
A:将选择的文件存进数组里面,上传完一个再上传第二个

Question 3

Q:我想同时上传多个文件欸
A:
1、websocket一次只能传递一个文件,要想多个文件,只能建立多个websocket连接。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/459858.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号