{"id":21148419,"url":"https://github.com/jacket-sikaha/chat-by-websocket","last_synced_at":"2025-07-20T08:34:59.560Z","repository":{"id":159358916,"uuid":"500358586","full_name":"jacket-sikaha/chat-by-websocket","owner":"jacket-sikaha","description":"基于websocket实现文件传输","archived":false,"fork":false,"pushed_at":"2024-07-04T02:03:42.000Z","size":700,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-21T07:43:22.543Z","etag":null,"topics":["nodejs","socket-io","websocket"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jacket-sikaha.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-06T08:51:50.000Z","updated_at":"2024-12-12T08:24:01.000Z","dependencies_parsed_at":"2024-06-24T03:40:15.445Z","dependency_job_id":"38a37537-ed36-4906-b227-0e3c93c4f4d1","html_url":"https://github.com/jacket-sikaha/chat-by-websocket","commit_stats":null,"previous_names":["jacket-sikaha/chat-by-websocket"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacket-sikaha%2Fchat-by-websocket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacket-sikaha%2Fchat-by-websocket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacket-sikaha%2Fchat-by-websocket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jacket-sikaha%2Fchat-by-websocket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jacket-sikaha","download_url":"https://codeload.github.com/jacket-sikaha/chat-by-websocket/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243589334,"owners_count":20315471,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nodejs","socket-io","websocket"],"created_at":"2024-11-20T09:25:17.940Z","updated_at":"2025-07-20T08:34:59.548Z","avatar_url":"https://github.com/jacket-sikaha.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 基于 websocket 设计一个文件传输助手网站\n\n#### demo\n\nhttps://ws.lee-sikaha.cloudns.ch\n\n- 文件上传最大支持500M，一次最多支持3个\n- 上传下载显示实时进度\n- 上传文件支持手动取消上传\n- 下载事件添加节流\n\n---\n#### 开发记录\n\n- 2025/6/19 连接完成同步在线人数数据，避免某一方因为数据不同步，消息列表渲染一个空指针组件导致页面崩溃\n- 2025/6/18 解决断线重连的提示问题，消息列表因为socketid的变化导致的显示错位问题\n\n---\n\n## 初期目标------5/27\n\n(htttp 协议版本)利用 nodejs（multer，express），Ajax 实现页面初步的上传下载\n\n掌握\n\nmulter([官网中文 API](https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md))的使用：storage 设置存储位置，上传文件预处理利用时间戳对文件的重命名\n\n回顾 express 创建静态资源服务器：static 的参数里写路径，目录名都行，都会对应到一个目录，在网页里这个目录名不需要带上，直接访问文件名即可；部署多个静态资源服务器，如果目录之间有同名文件，则按 static 执行顺序找，找到就停止，找不到就下一个\n\n响应返回资源的设置：\n\n```js\n//默认情况(响应头不调整的情况)\n//相当于跳转，但实际是返回资源给浏览器显示\nres.sendFile(__dirname + '/index.html');\n//区分\n//下载所需响应头\nres.setHeader('Content-type', 'application/octet-stream');\n//！！！响应头里不允许带中文\nres.setHeader('Content-Disposition', `attachment;filename=asd.jpg`);\nres.sendFile(__dirname + '/uploads/QQ图片20200621185630.jpg');\n```\n\n[下载响应头说明补充链接](https://cloud.tencent.com/developer/article/1417956#:~:text=http%20%E5%8D%8F%E8%AE%AE%E5%AE%9E%E7%8E%B0%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD%E6%97%B6%EF%BC%8C%E9%9C%80%E8%A6%81%E5%9C%A8%20%E6%9C%8D%E5%8A%A1%E5%99%A8%20%E8%AE%BE%E7%BD%AE%E5%A5%BD%E7%9B%B8%E5%85%B3%E5%93%8D%E5%BA%94%E5%A4%B4%EF%BC%8C%E5%B9%B6%E4%BD%BF%E7%94%A8%E4%BA%8C%E8%BF%9B%E5%88%B6%E4%BC%A0%E8%BE%93%E6%96%87%E4%BB%B6%E6%95%B0%E6%8D%AE%EF%BC%8C%E8%80%8C%E5%AE%A2%E6%88%B7%E7%AB%AF%EF%BC%88%E6%B5%8F%E8%A7%88%E5%99%A8%EF%BC%89%E4%BC%9A%E6%A0%B9%E6%8D%AE%E5%93%8D%E5%BA%94%E5%A4%B4%E6%8E%A5%E6%94%B6%E6%96%87%E4%BB%B6%E6%95%B0%E6%8D%AE%E3%80%82%20%E5%9C%A8,http%20%E5%93%8D%E5%BA%94%E6%8A%A5%E6%96%87%E4%B8%AD%EF%BC%8C%20Content-type%20%E5%92%8C%20Content-Disposition%20%E6%98%AF%E6%9C%80%E5%85%B3%E9%94%AE%E7%9A%84%E4%B8%A4%E4%B8%AA%E5%93%8D%E5%BA%94%E5%A4%B4%E3%80%82)\n\n## 中期目标------5/30\n\n###### 仿照 HTTP 的文件上传下载改成**websocket 协议的版本**\n\n###### 补充资料\n\n[socket.io 官网的案例 https://socket.io/get-started/chat](https://socket.io/get-started/chat)\n\n[socket.io emit 方法支持文件传输的数据类型](https://socket.io/blog/introducing-socket-io-1-0/#binary-support)\n\n[前端上传文件的方法总结与利弊](https://www.cnblogs.com/soraly/p/8441589.html)\n\n- 准备工作，确定能编写 websocket 的工具------socket.io\n\n- 仿照[官网的案例](https://socket.io/get-started/chat)，我们就可以很快的搭建一个 websocket 环境\n\n- 我们实现文件传输就得确认如何从前端拿取数据，用什么数据类型进行存储，传输，这是整个项目的核心。基于 api 提供的 emit 方法和[补充内容](https://socket.io/blog/introducing-socket-io-1-0/#binary-support)，socket 是可以接收很多种类的参数，自然也包括文件，但限定一下几种类型 Blob，ArrayBuffer，File\n\n  ![image-20220530231529952](C:\\Users\\98755\\AppData\\Roaming\\Typora\\typora-user-images\\image-20220530231529952.png)\n\n- 再了解[前端通过 input[type=file]的标签拿取文件数据的方式](https://www.cnblogs.com/soraly/p/8441589.html)后，采用**[fileReader](https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/FileReader)**的方式，因为其余两种方式对 HTTP 的依赖性较强，websocket 难以处理\n\n- 数据到 node 服务端就到了**上传步骤**，就需要有能处理这种 ArrayBuffer 类型的工具：fs，path（fs 负责将数据写入进文件，path 处理文件的路径问题）\n\n- 最大问题，fs.writeFile 方法对写入数据类型会有限制：ArrayBuffer 不完全等于 Buffer\n\n  ![image-20220531001815887](C:\\Users\\98755\\AppData\\Roaming\\Typora\\typora-user-images\\image-20220531001815887.png)\n\n  解决办法就是类型转换https://blog.csdn.net/iningwei/article/details/100143603 let buffer = Buffer.from(arraybuffer)//ArrayBuffer 转 Buffer\n\n- 写入成功执行其回调函数时，我们就可以提供对应的下载链接给前端，借助服务端的下载接口完成下载（借助 http 协议去实现下载，因为下载是属于用户自身需求，不需要共享）\n\n- 后续问题，对 1M 以上的文件无法上传\n\n## 解决问题的关键，文件分片上传与合并------6/2（生产模式下无法解决）\n\n大的文件读取 readAsArrayBuffer 对本机的内存消耗过大，导致 websocket 重连\n\nhttps://www.bilibili.com/video/BV1RK4y147uV?share_source=copy_web\n\n## 直接突破：修改 websocket 的心跳机制和传输数据大小限制------6/5\n\n部署之后分片上传失败，初步怀疑是 websocket 的原因---完成一次请求就会重启\n\n于是直接修改配置：\n\n- maxHttpBufferSize: 50000000,//50M pingTimeout: 30000,//单次 socket 消息发送的最大连接时长，超过就重连\n\n  https://socket.io/docs/v4/server-options/#transports\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjacket-sikaha%2Fchat-by-websocket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjacket-sikaha%2Fchat-by-websocket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjacket-sikaha%2Fchat-by-websocket/lists"}