纯前端图片预览:FileReader与IE滤镜实现方案

作者:桌面漫游时间:2026-10-30 05:49:19浏览:607

本文详解如何在纯前端实现图片预览功能。针对现代浏览器,利用HTML5 FileReader的readAsDataURL方法生成Data URI;针对IE5.5至9,采用DXImageTransform.Microsoft.AlphaImageLoader滤镜进行降级处理。同时解决IE11安全限制导致的fakepath问题,并介绍使用window.URL.createObjectURL优化大图片性能的方案。

纯前端图片预览方案概述

图片上传是常见功能,而图片预览则是上传流程中不可或缺的一环。以往的做法是监听input[type=file]的onchange事件,一旦路径改变便立即将文件上传至服务器,随后获取返回的图片路径并赋值给img元素。即便不考虑异步提交文件的复杂性,服务端清理这些临时预览图片也增加了额外的工作负担。

偶然在MDN文档中发现了纯前端实现图片预览的相关资料,经整理后记录如下,供日后查阅参考。

FileReader对象详解

一、准备工作1:FileReader对象

FileReader是HTML5引入的新特性,专门用于读取Blob和File类型的数据。其具体用法如下:

(1)构造方式

var fr = new FileReader(); (2)属性

readyState:类型为unsigned short,表示FileReader实例的当前状态(EMPTY——0,尚未加载任何数据;LOADING——1,数据正在加载;DONE——2,已完成全部读取请求),该属性只读。

result:表示读取到的文件内容,该属性只读。

error:类型为DOMError,表示在读取文件过程中发生的错误,该属性只读。

(3)方法

abort():中止读取操作,并将readyState设置为DONE。若在未执行读取操作时调用此方法,将抛出DOM_FILE_ABORT_ERR异常。

readAsArrayBuffer(Blob blob):读取数据,result属性将被设置为ArrayBuffer类型。

readAsText(Blob blob [, encoding='utf-8']):读取数据,result属性将被设置为String类型。

readAsBinaryString(Blob blob):读取数据,result属性将被设置为原始二进制数据。

readAsDataURL(Blob blob):读取数据,result属性将被设置为Data URI Scheme形式(具体可参考《JS魔法堂:Data URI Scheme介绍》)。

(4)事件

onload:读取数据成功后触发。

onerror:读取数据时抛出异常时触发。

onloadstart:读取数据前触发。

onloadend:读取数据后触发,会在onload或onerror之后触发。

onabort:中止读取后触发。

onprogress:读取过程中周期性触发。

(5)浏览器支持情况

Firefox 3.6+,Chrome 7+,IE 10+

IE滤镜AlphaImageLoader应用

二、准备工作2:DXImageTransform.Microsoft.AlphaImageLoader滤镜

(1)作用:主要用于对图片进行透明处理(注:IE5.5至6版本并不支持透明的PNG格式)。

(2)在CSS样式中的使用方式


#preview{
 filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale,src="dummy.png");
}

(3)在JavaScript中的使用方式


var preview = document.getElementById('preview');
preview.style.filter = preview.currentStyle.filter + ";progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale,src='dummy.png')";
preview.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src="dummy1.png";

(4)属性说明

enabled:可选项,用于设置滤镜是否激活。取值范围为true(默认值)或false。

sizingMethod:可选项,用于设置滤镜作用的图片在容器边界内的显示方式。取值范围包括crop(剪切图片以适应容器尺寸)、image(默认值,增大或缩小容器尺寸以适应图片尺寸)以及scale(缩放图片以适应容器尺寸)。

src:必填项,使用绝对或相对URL指向背景图片。当URL为用户计算机本地地址时有效;但若img元素的src直接指向用户计算机本地地址,则会抛出“不允许访问本地文件系统”的异常。

图片预览功能实现代码

三、具体实现方案

接下来,我们将利用FileReader的readAsDataURL方法获取Data URI Scheme来实现图片预览功能;对于IE5.5至9版本,则使用滤镜DXImageTransform.Microsoft.AlphaImageLoader进行降级处理。

HTML片段示例:


<style type="text/css">
#preview{
  width: 100px;
  height: 100px;
}
</style>
<!--[if lte IE 9]>
<style type="text/css">
  #preview{
    filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale);
  }
</style>
<![endif]-->

<input type="file" onchange="showPreview(this);"/>
<div id="preview">
</div>

JavaScript片段示例:


var preview = function(el){
  var pv = document.getElementById("preview");
  // IE5.5~9使用滤镜
  if (pv.filters && typeof(pv.filters.item) === 'function'){
    pv.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = el.value;
  }
  else{
    // 其他浏览器和IE10+(不支持滤镜)则使用FileReader
    var fr = new FileReader();
    fr.onload = function(evt){
      var pvImg = new Image();
      pvImg.style.width = pv.offsetWidth + 'px';
      pvImg.style.height = pv.offsetHeight + 'px';
      pvImg.src = evt.target.result;
      pv.removeChild(0);
      pv.appendChild(pvImg);
    };
    fr.readAsDataURL(el.files[0]);
  }
};

IE11兼容性问题与解决

四、常见坑点与解决

由于IE11出于安全考虑,使得在input[type=file]元素上通过value、outerHTML和getAttribute等方式无法获取用户所选文件的真实地址,只能获取到形如 C:\fakepath\文件名称 的路径。因此,如果使用的是IE11但文档模式设置为10以下版本,则无法实现图片预览功能。

解决办法1:在head标签下加入以下代码: <meta http-equiv="X-UA-Compatible" content="IE=Edge"> 。这样可以告知IE浏览器默认使用当前IE的最高版本来解析和渲染网页。

解决办法2:采用 document.selection.createRangeCollection() 获取真实地址,具体操作步骤如下:


// 假设fileEl就是[type=file]元素
fileEl.select();
var filePath = document.selection.createRangeCollection()[0].htmlText; 

createObjectURL性能优化方案

五、补充方案:使用window.URL.createObjectURL替代FileReader

通过FileReader的readAsDataURL方法获取的Data URI Scheme会生成一串很长的base64字符串。若图片较大,字符串长度会更长,当页面发生reflow(重排)时会导致性能下降。解决方案如下:

1. 对预览用的img标签使用绝对定位,使其脱离正常文档流,从而与文档的其他元素无关,这样在页面发生reflow时不会影响性能。

2. 采用 window.URL.createObjectURL(Blob blob) 生成数据链接。


var createObjectURL = function(blob){
 return window[window.webkitURL ? 'webkitURL' : 'URL']['createObjectURL'](blob);
};

注意: window.URL.createObjectURL 生成的数据链接是独占内存的,因此若不再使用,需要调用 window.URL.revokeObjectURL(DOMString objUrl) 来释放内存。在刷新页面时,系统也会自动释放相关内容。


var resolveObjectURL = function(blob){
 window[window.webkitURL ? 'webkitURL' : 'URL']['revokeObjectURL'](blob);
};

以上就是本文的全部内容,希望对大家的学习有所帮助。

作者最新文章