应用右键上传,类似右键文件上传至百度云(websocket分包传输文件、cmd命令唤醒浏览器、IO读取文件)

一、分析

  1. 将jar包整合成window服务,编写bat文件。具体参考:https://blog.csdn.net/czx2282885707/article/details/85797840
  2. 保证jar包整合的window服务处于启动状态。未安装则提示安装,安装完则需要启动。
  3. 右键点击文件,点击上传。此时会先唤醒浏览器打开指定页面,检查是否登陆,未登陆则提示登陆,并取消此次上传。
  4. 若已登陆,通过websocket,将本地window服务与浏览器页面建立连接。
  5. 读取本地文件,通过websocket分包传输数据给浏览器页面。
  6. 最后,浏览器将数据发送至服务器。

jar包制成的本地window服务作用:
(1)读取本地文件
(2)唤醒浏览器
(3)进行websocket连接,传输读取到的本地文件数据至前端。

技术分析:
(1)websocket如何分包发送?读取时使用接口回调。
(2)浏览器如何唤醒?使用cmd命令。
(3)本地文件如何读取?使用IO流。

二、分层及其代码实现

  1. 唤醒服务:传入路径,打开默认浏览器指定页面。

    @Component
    public class OpenBrowseService {
        public Process openBrowse(String url) throws IOException {
            return Runtime.getRuntime().exec(String.format("cmd /c start %s", url));
        }
    }
    

    主要参考Java如何调用cmd命令,cmd命令启动浏览器等文章。

  2. 读取服务:传入路径,包大小,以及一个回调接口。

    @Component
    public class FileReadService {
        public void readFile(String path, int packLength, ReadFileCallback callback) {
        	//path为空,返回,后续完善
            if (StringUtils.isEmpty(path)) {
                return;
            }
            // 尝试根据路径读取本地文件
            try (InputStream is = Files.newInputStream(Paths.get(path))) {
                byte[] bytes=new byte[packLength <= 0 ? 4096 : packLength];
                int r;
                while ((r = is.read(bytes)) >= 0){
                    callback.run(bytes, r);
                }
            } catch (Exception e) {}
        }
    
        interface ReadFileCallback {
            void run(byte[] bytes, int length) throws IOException, EncodeException;
        }
    
    }
    
  3. websocket服务:连接、文件数据传送。

    主要在OnMessage中将文件传输分成三部分:

        @OnMessage
        public void onMessage(String path,boolean flag) throws IOException, EncodeException {
            if(flag){
                // 生成唯一fileId
                String fileId = UUID.randomUUID().toString();
                Path target = Paths.get(path);
                // 1、文件传输开始
                sendMessage(Message.of(Message.MessageType.SEND_FILE_START, new SendFileMessage(){{
                    setFileId(fileId);
                    setFileLength(Files.size(target));
                    setFileName(Paths.get(path).getFileName().toString());
                }}));
    
                //seq自增
                AtomicInteger seq = new AtomicInteger();
                // 2、文件传输过程
                fileReadService.readFile(path, 4096, (bytes, length) -> {
                    SendFilePackMessage message = new SendFilePackMessage();
                    message.setFileId(fileId);
                    message.setSeq(seq.incrementAndGet());
                    message.setData(bytes);
                    sendMessage(Message.of(Message.MessageType.FILE_PACK, message));
                });
    
                // 3、文件传输结束
                sendMessage(Message.of(Message.MessageType.SEND_FILE_FINISH, new SendFileMessage(){{
                    setFileId(fileId);
                }}));
            }
        }
        /**
         * 服务器主动提推送消息
         *
         * @param obj 文件内容
         * @throws IOException io异常抛出
         */
        public void sendMessage(Object obj) throws IOException, EncodeException {
            this.session.getBasicRemote().sendObject(obj);
        }
    
    }
    

    主要参考:springboot整合websocket,websocket如何传输Java对象。

三、总结:

需要清晰整个流程。
(1)首先,安装window服务,启动该服务。
(2)右键上传文件,如客户端/浏览器页面已打开,则进行websocket连接,否则尝试唤醒客户端/浏览器页面。
(3)IO接口读取数据,websocket传送数据到客户端/浏览器页面。
(4)最后由客户端/浏览器页面发送请求至服务器。
整个流程完毕。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
WebSocket协议本身并没有针对大文件上传的特定支持,但你可以使用WebSocket来实现大文件的分片上传。 基本思路是将大文件分成较小的块进行上传,然后在服务器端将这些块重新组合成完整的文件。以下是一个简单的示例代码,使用JavaScript和Node.js来实现大文件WebSocket上传: 在客户端(使用JavaScript): ```javascript const socket = new WebSocket('ws://your-server-url'); const fileInput = document.getElementById('file-input'); fileInput.addEventListener('change', () => { const file = fileInput.files[0]; const chunkSize = 1024 * 1024; // 每个块的大小(1MB) let offset = 0; socket.onopen = () => { while (offset < file.size) { const chunk = file.slice(offset, offset + chunkSize); socket.send(chunk); offset += chunkSize; } socket.close(); }; socket.onerror = (error) => { console.error('WebSocket error:', error); }; }); ``` 在服务器端(使用Node.js): ```javascript const WebSocket = require('ws'); const fs = require('fs'); const wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', (ws) => { let fileStream; ws.on('message', (chunk) => { if (!fileStream) { // 创建一个新文件以存储上传的数据 fileStream = fs.createWriteStream('uploaded-file'); } fileStream.write(chunk); }); ws.on('close', () => { if (fileStream) { fileStream.end(); console.log('File upload completed.'); } else { console.log('Connection closed before any data was received.'); } }); }); ``` 这只是一个简单的示例,实际应用中还需要处理更多的错误和边界情况。同时,你也可以根据自己的需求进行调整和改进。 希望这能帮到你!如果还有其他问题,请继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT学习小镇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值