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

springboot整合websocket(二)上传文件(引导篇)

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

springboot整合websocket(二)上传文件(引导篇)

springboot整合websocket(二)上传文件(引导篇)

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


接上一章,这次我们把文件上传的坑给填了。
不过之前的内容我就没有保留,因为上传文件和发消息在一起,需要一些其他操作,我会在末尾说明一下,也不难。

1、回顾一下

上次提到有一个方法:

void onMessage(Session session, byte[] message);

这个是用来上传文件用的,先解释一下 byte[] 这个参数。
好吧~ 大家猜的没错,这个就是我们文件的二进制流。

所以说,我们要干两件事:
第一,我们js要获得文件,并转成二进制流发过来
第二,在上传之前,我们需要知道文件的名字,因为这个二进制流是一个数组,没法知道文件的名字!(实测,js不能修改这个二进制流哦)

2、先做后端吧

说一下重点
1、在onMessage(string)中用session.getUserProperties()将文件名存起来,并删除已有的文件(因为要追加到文件末尾)
2、在onMessage(byte[])中保存文件,至于我那里为什么要追加,在后面会说(透露一点,文件要切分上传,所以要追加)
3、在onClose中将关闭原因打印一下(埋个雷,一会要用)

@Log4j2
@Controller
@ServerEndpoint("/websocket")
public class baseWebsocketController
{

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

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

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

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

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

    //响应字节流
    @OnMessage
    public void onMessage(Session session, byte[] message) throws Exception
    {
        // 1、先拿到文件名
        final String filename = (String) session.getUserProperties().get("filename");
        // 2、追加到该文件
        File file = new File(getProjectRootPath(), filename);
        //输出一下文件路径
        System.out.println(file.getCanonicalPath());
        try (OutputStream os = new FileOutputStream(file, true)) {
            os.write(message, 0, message.length);
        }
        catch (IOException e) {
            e.printStackTrace();
        }

        sendAll("[" + session.getId() + "]上传了一个文件[" + filename + "]");
    }

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

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

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

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

    private void sendAll(String message)
    {
        for (Session s : sessions.values()) {
            //获得session发送消息的对象
            //Basic是同步, 会阻塞
            //Async是异步, 这个会有多线程并发导致异常, 发送消息太快也会有并发异常, 需要有 消息队列 来辅助使用
            final RemoteEndpoint.Basic remote = s.getBasicRemote();
            try {
                //发送消息
                remote.sendText(message);
            }
            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 "";
        }
    }
}


3、页面 3.1 第一版傻白甜的页面

说一下重点

1、通过FileReader将文件读取成二进制流
let reader = new FileReader();
reader.readAsArrayBuffer(files[0]);
2、发送的时候一样用的是webSocket.send()

再看看效果




  
  websocket-demo
  
  


  


大家开心的上传文件,然后就会有这么一个问题

没有这个的童鞋,就选个大一点的文件

看一下后台的报错
(检查一下onClose是不是和我上面的一样,要打印一下关闭原因哦~)

No async message support and buffer too small. Buffer size: [8,192], Message size: [2,254,618]

这个意思是说-------->
文件:我有2,254,618B,我的很大,你忍一下
Websocket:不行,我只有8192B,太大了,忍不了,放不开

所以啊,我们要将文件切开,挨个上传,一次传一点,这篇有点长,我们下篇再说

End


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

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

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

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