高效的图片预览方案

348 阅读3分钟

传统图片预览解决方案

对于目前很多应用场景,都会存在着上传头像、上传相册、上传图标等业务场景,而我们作为用户在使用这些功能时,往往都会涉及到预览以及裁剪图片的功能,但是在使用这些功能的时候,我们可能会发现当我们点击上传图片之后需要等待一定的时间才能进行预览,这是因为对于传统的图片上传模式,它所采用的解决方案是:用户选择图片,然后将其上传到服务器,服务器返回一个可访问的url地址作为图片资源给用户访问,这就会导致用户需要先等待图片上传,这个等待时间无疑导致了不太友好的用户体验,甚至用户有裁剪需求时还会发起两次网络请求。

Screenshot_20230211_090340_com.ss.android.ugc.awe.png

更高效的图片预览方案

所谓更高效的图片预览方案,其本质上是将用户选择图片后的上传服务器操作进行优化,使其在本地进行,将图片资源转换成可访问的数据,给用户进行访问,同时异步的上传服务器,从而提升用户体验,对于裁剪需求,也减少了网络请求从而提升了性能。

具体实现

// 获取元素
const ipt = document.querySelector("input");
const preview = document.querySelector("#preview");

ipt.onchange = function(e) {
  // 创建一个流式数据读取器
  const reader = new FileReader();
  reader.onload = function(e) {
    // 读取转换后的图片数据
    console.log(e.target.result);
    // 预览
    preview.src = e.target.result;
    // 这里可以进行ajax操作
  }
  reader.readAsDataURL(this.files[0]);
}

实现结果:

image.png

代码解释: 因图片资源的特定格式,对于图片资源的读取,需要使用FileReader来进行读取,通过readAsDataURL方法将其转换成Base64的格式,由于读取是需要一定时间的,因此这个操作是异步的,但是这个时间肯定会比上传到服务器要短,我们可以给reader绑定load事件,当读取完成时,进行一系列操作,比如将资源给img标签访问,异步上传到服务器等。

DataUrl

在上述结果截图中,可以仔细关注下控制台输出,特别是是红框的内容,这是我们将图片转换成base64格式后的数据。也就是一个DataUrl,DataUrl本质上就是用一个固定格式的字符串,它可以替代url地址,从而进行数据的访问。

DataUrl:data:[<mediatype>][;base64],<data>,格式:data:mediatype是一个MIME类型,比如image/png;base64表示后面的数据格式是原始格式,还是base64格式。

上述截图中的数据:data:image/png;base64,iVBORw0KG...

这个字符串的用处不仅仅在于这里的读取文件数据,还可以动态的生成js代码,比如:<script src="data:application/javascript,alert('hello')"></script>,一些第三方组件库中也有类似的操作。

base64

在上述DataUrl中的data数据,如果是一些原始格式对于纯文本的数据没有什么影响,但是对于二进制的数据(比如图片)则需要进行编码,常见的编码格式:base64,base64总共由52个字母(大小写),10个数字(0-9),加号(+),斜杠(/)组成,其作用是将二进制数据转换成可打印字符。