一、分析
- 将jar包整合成window服务,编写bat文件。具体参考:https://blog.csdn.net/czx2282885707/article/details/85797840
- 保证jar包整合的window服务处于启动状态。未安装则提示安装,安装完则需要启动。
- 右键点击文件,点击上传。此时会先唤醒浏览器打开指定页面,检查是否登陆,未登陆则提示登陆,并取消此次上传。
- 若已登陆,通过websocket,将本地window服务与浏览器页面建立连接。
- 读取本地文件,通过websocket分包传输数据给浏览器页面。
- 最后,浏览器将数据发送至服务器。
jar包制成的本地window服务作用:
(1)读取本地文件
(2)唤醒浏览器
(3)进行websocket连接,传输读取到的本地文件数据至前端。
技术分析:
(1)websocket如何分包发送?读取时使用接口回调。
(2)浏览器如何唤醒?使用cmd命令。
(3)本地文件如何读取?使用IO流。
二、分层及其代码实现
-
唤醒服务:传入路径,打开默认浏览器指定页面。
@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命令启动浏览器等文章。
-
读取服务:传入路径,包大小,以及一个回调接口。
@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; } }
-
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)最后由客户端/浏览器页面发送请求至服务器。
整个流程完毕。