流水不争先,争的是滔滔不绝

WEBIM系统粘贴图片预览上传react+原生JS解决方案

即时通讯软件开发 云聊IM 1058℃

需求背景

最近在做一个IM即时通讯系统的开发工作,其中有一项需求是:在第三方截图软件(如QQ、微信、钉钉)截图后,能在聊天输入框中粘贴该图片,支持预览,点击发送后能够上传。

由于IM的特殊性,不同于常规的B端项目,其对用户体验的要求极高,高频的交互操作,不允许百毫秒或以上级别的延迟。

尝试过采用github上的一些富文本编辑框插件,无法完全满足需求,存在一些缺陷,踩了一些坑。所以打算采用最原生,最稳定的方案,类似网页版微信。

操作流程

用户使用第三方软件截图 –》在输入框中粘贴 –》弹框显示图片预览 –》点击发送,http请求,同时展示临时消息模板 –》待响应拿到网络url,用其替换临时消息

具体方案

前三步可以看做一个整体,要做的事情也不多:监听输入框的onPaste事件,使用FileReader对象读取图片为base64格式并展示在预览框中,如下

输入框onPaste事件监听

这里创建了一个FileReader构造函数,其为HTML5新特性之一。代码中将其读取成了DataURL格式,读取过程为异步事件,使用onload作为读取监听回调,并通过参数e.target.result获取图片的base64格式,渲染到img标签的src属性中来获取图片预览。除此格式之外,还提供了多种格式的读取:

FileReader实例拥有的四个方法

其中三个是用来读取文件,另一个是用来中断读取的,功能如下:

readAsText:该方法有两个参数,其中第二个参数是文本的编码方式,默认值为 UTF-8。这个方法非常容易理解,将文件以文本方式读取,读取的结果即是这个文本文件中的内容。 

readAsBinaryString:该方法将文件读取为二进制字符串,通常我们将它传送到后端,后端可以通过这段字符串存储文件。 

readAsDataURL:这是例子程序中用到的方法,该方法将文件读取为一段以 data: 开头的字符串,这段字符串的实质就是 Data URL,Data URL是一种将小文件直接嵌入文档的方案。这里的小文件通常是指图像与 html 等格式的文件。

需要注意的是,无论读取成功或是失败,方法并不会返回读取结果,这一结果(储存在result属性中)要用FileReader处理事件去获取:

FileReader 包含了一整套完成的事件模型

读取file对象的同时,需要将其存储在state中,在用户点击发送时使用:

发送上传图片并展示临时消息列表

由于每个用户的工作环境,网速不能确定,考虑到图片上传可能占用一些时间,如此时不显示图片,会让用户造成误解,影响用户体验,所以加入了临时消息列表功能,流程如下:

用户点击发送按钮    –》消息列表先展示base64图片,同时发送http请求传递file对象    –》等待服务器返回网络url    –》删除相应临时消息,展示真实图片

这里使用时间戳作为临时消息ID,以确保临时消息的对应关系,并保证唯一性。

使用原生XHR传递并监听ajax请求。

图片渲染完成后消息列表滚动条自动滚动到列表底部。

创建同为HTML5新特性的FormData对象,并使用append方法为对象添加file项,然后发送。成功拿到网络url后,删除相应临时消息并展示真实消息。

最后一点,也是前端工程师必须注意和解决的一点:API兼容性。

本方案,兼容性最大的API瓶颈是paste方法,请使用者注意。can I use查询如下:

方案兼容性

版权声明:部分文章、图片等内容为用户发布或互联网整理而来,仅供学习参考。如有侵犯您的版权,请联系我们,将立刻删除。
点击这里给我发消息