博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HTML5 FileReader
阅读量:4133 次
发布时间:2019-05-25

本文共 8479 字,大约阅读时间需要 28 分钟。

HTML5 FileReader

 NOTE: 在chrome浏览器上本地测试的时候,即以file://xxx这种形式测试本文中的demo,会出现FileReader读取不到内容的情况,表现为FileReader的result为空或者FileReader根本就没有去读取文件内容,FileReader各个事件没有触发;这种情况我想应该是类似于chrome不允许添加本地cookie那样,chrome也不允许以file://xxx这种页面上的js代码访问文件内容;解决办法很简单,只需要将测试文件放到一个web服务器上,以http://xxx形式访问即可。

一、读取文件内容

       一文中主要介绍获取文件句柄的方法,接下来我们就要利用该文件句柄来读取文件内容,这是通过FileReader来实现的,通过FileReader接口,我们可以异步地将文件内容加载到内存中,赋予某个js变量。

       FileReader具体支持哪些方法和事件,这里就不介绍了,有兴趣的可以去w3c官网上看看介绍,这里主要介绍一下FileReader两个常见应用。

1、预览本地图片

       这里主要用到FileReader的readAsDataURL方法,通过将图片数据读取成Data URL的方法,将图片展示出来,关于。

示例脚本:

function fileSelect(e) {    e = e || window.event;         var files = e.target.files;  //FileList Objects        var ireg = /image\/.*/i,        p = document.getElementById('Preview');             var ul = document.getElementById('Errors');    for(var i = 0, f; f = files[i]; i++) {        if(!f.type.match(ireg)) {            //设置错误信息            var li = document.createElement('li');            li.innerHTML = '
  • ' + f.name +'不是图片文件.
  • '; ul.appendChild(li); continue; } var reader = new FileReader(); reader.onload = (function(file) { return function(e) { var span = document.createElement('span'); span.innerHTML = ''+ file.name +''; p.insertBefore(span, null); }; })(f); //读取文件内容 reader.readAsDataURL(f); }}if(window.File && window.FileList && window.FileReader && window.Blob) { document.getElementById('Files').addEventListener('change', fileSelect, false);} else { document.write('您的浏览器不支持File Api');}
     

    由以上代码可知,调用FileReader的readAsDataURL接口,将启动异步加载文件内容,通过给reader监听一个onload事件,将数据加载完毕后,在onload事件处理中,通过reader的result属性即可获得文件内容,。

            NOTE:在示例中,我给图片指定了一个height:75px的css样式,主要是为了让浏览器对图片进行等比缩放处理,所以在浏览器中展示出来的图片并不是原始大小的图片,而是经过浏览器自动等比缩放的图片;如果需要查看原始尺寸图片,可点击相应图片;再次单击该图片,则恢复小图片。

    2、预览文本文件

            这里主要用到FileReader的readAsText,对于诸如mimetype为text/plain、text/html等文件均认为是文本文件,即minetype为text开头都能在本例中预览。

    NOTE:由于需要在页面上预览文本,如果使用innerHTML插入文本的话,则需要对html中一些特殊字符进行实体编码,这样才能保证正常显示文本。

    简易的encodeHTML方法:

    function encodeHTML(source) {    return source            .replace(/&/g, '&')            .replace(//g, '>')            .replace(/"/, '"')            .replace(/'/, ''');};function fileSelect(e) {    e = e || window.event;         var files = e.target.files;  //FileList Objects        var ireg = /text\/.*/i,        p = document.getElementById('Preview');             var ul = document.getElementById('Errors');    for(var i = 0, f; f = files[i]; i++) {        console.log(f.type);        if(!f.type.match(ireg)) {            //设置错误信息            var li = document.createElement('li');            li.innerHTML = '
  • ' + f.name +'不是文本文件.
  • '; ul.appendChild(li); continue; } var reader = new FileReader(); reader.onload = (function(file) { return function(e) { var div = document.createElement('div'); div.className = "text" div.innerHTML = encodeHTML(this.result); p.insertBefore(div, null); }; })(f); //读取文件内容 reader.readAsText(f); }} if(window.File && window.FileList && window.FileReader && window.Blob) { document.getElementById('Files').addEventListener('change', fileSelect, false);} else { document.write('您的浏览器不支持File Api');}

    二、分段读取文件内容(slice)

          有的时候,一次性将一个大文件读入内存,并不是一个很好的选择(如果文件太大,使用FileReader读取文件内容,可能直接导致浏览器崩溃),w3c也想到了这种情况,所以html5允许对文件进行分段读取。

    chrome以及firefox已经将File slice api调整为如下:

    var blob;if(file.webkitSlice) {  //Blob中的方法    blob = file.webkitSlice(start, end + 1, 'text/plain;charset=UTF-8');} else if(file.mozSlice) {    blob = file.mozSlice(start, end + 1, 'text/plain;charset=UTF-8');}

     本例使用了FileReader的onloadend事件来检测读取成功与否,如果用onloadend则必须检测一下FileReader readyState,因为read abort时也会触发onloadend事件,如果我们采用onload,则可以不用检测readyState。

    示例代码:

    function readBlob(start, end) {    var files = document.getElementById('file').files;         if(!files.length) {        alert('请选择文件');        return false;    }         var file = files[0],        start = parseInt(start, 10) || 0,        end = parseInt(end, 10) || (file.size - 1);             var r = document.getElementById('range'),        c = document.getElementById('content');             var reader = new FileReader();         reader.onloadend = function(e) {        if(this.readyState == FileReader.DONE) {            c.textContent = this.result;            r.textContent = "Read bytes: " + (start + 1) + " - " + (end + 1) + " of " + file.size + " bytes";        }    };    var blob;         if(file.webkitSlice) {  //Blob中的方法        blob = file.webkitSlice(start, end + 1, 'text/plain;charset=UTF-8');    } else if(file.mozSlice) {        blob = file.mozSlice(start, end + 1, 'text/plain;charset=UTF-8');    }         reader.readAsBinaryString(blob);};try {    document.getElementById('buttons').addEventListener('click', function(e) {        if(e.target.tagName.toLowerCase() == 'button') {            var start = e.target.getAttribute('data-start'),                end = e.target.getAttribute('data-end');                             readBlob(start, end);        }      });} catch(ex) {    alert('something error happens!')

    NOTE:readAsBinaryString这个方法,读取的二进制字符串,在页面显示,出现中文乱码,不知道怎么解决,如果用reader.readAsText即可正常显示中文;在w3c官网上:binary string, in which every byte is represented by an integer in the range [0..255],而中文却不在[0...255]内,难道是因为这样才出现乱码?

    三、FileReader进度条

           既然FileReader是异步读取文件内容,那么就应该可以监听它的读取进度。事实上,FileReader的onloadstart以及onprogress等事件,可以用来监听FileReader的读取进度。

           在onprogress的事件处理器中,提供了一个ProgressEvent对象,这个事件对象实际上继承了Event对象,提供了三个只读属性:lengthComputable、loaded、total;通过以上几个属性,即可实时显示读取进度。w3c官网上对它的定义如下:

    interface ProgressEvent : Event {  readonly attribute boolean lengthComputable;  readonly attribute unsigned long long loaded;  readonly attribute unsigned long long total;};

     如果处理的文件太大,可能会导致浏览器崩溃(chrome下一般都会崩溃掉,而firefox则不会,不过会触发FileReader的onerror事件,文件读取失败),所以为了安全地、正常地观察到文件读取进度,我们采用分段读取的方法来测试FileReader的进度条。

    HTML代码如下:

    分度读取文件:

    JS代码如下:
    var h = {    init: function() {        var me = this;                 document.getElementById('File').onchange = me.fileHandler;        document.getElementById('Abort').onclick = me.abortHandler;                 me.status = document.getElementById('Status');        me.progress = document.getElementById('Progress');        me.percent = document.getElementById('Percent');                 me.loaded = 0;        //每次读取1M        me.step = 1024 * 1024;        me.times = 0;    },    fileHandler: function(e) {        var me = h;                 var file = me.file = this.files[0];                 var reader = me.reader = new FileReader();                 //        me.total = file.size;                 reader.onloadstart = me.onLoadStart;        reader.onprogress = me.onProgress;        reader.onabort = me.onAbort;        reader.onerror = me.onerror;        reader.onload = me.onLoad;        reader.onloadend = me.onLoadEnd;        //读取第一块        me.readBlob(file, 0);    },    onLoadStart: function() {        var me = h;    },    onProgress: function(e) {        var me = h;                 me.loaded += e.loaded;        //更新进度条        me.progress.value = (me.loaded / me.total) * 100;    },    onAbort: function() {        var me = h;    },    onError: function() {        var me = h;             },    onLoad: function() {        var me = h;        if(me.loaded < me.total) {            me.readBlob(me.loaded);        } else {            me.loaded = me.total;        }    },    onLoadEnd: function() {        var me = h;             },    readBlob: function(start) {        var me = h;                 var blob,            file = me.file;                 me.times += 1;                 if(file.webkitSlice) {            blob = file.webkitSlice(start, start + me.step + 1);        } else if(file.mozSlice) {            blob = file.mozSlice(start, start + me.step + 1);        }                 me.reader.readAsText(blob);    },    abortHandler: function() {        var me = h;                 if(me.reader) {            me.reader.abort();        }    }};h.init();

      例子中的进度条采用元素来实现的。

            每次读取1M的字节(你也可以随便改步长,比如说一次一个字节,然后传一个大小为几字节的文件,也能很好地观察到进度),在一次读取完毕后,onload事件中开启下一次读取,直至整个文件都读取完毕。

             如果您的浏览器支持html5,您可以试一下:

    分度读取文件:

            这个示例中,没有限制文件大小,读取大文件时,也不会出现浏览器崩溃的情况,可以正常观察到文件的读取进度。

    转自

    转载地址:http://gtjvi.baihongyu.com/

    你可能感兴趣的文章
    TitledBorder 设置JPanel边框
    查看>>
    DBCP——开源组件 的使用
    查看>>
    抓包工具
    查看>>
    海量数据相似度计算之simhash和海明距离
    查看>>
    DeepLearning tutorial(5)CNN卷积神经网络应用于人脸识别(详细流程+代码实现)
    查看>>
    DeepLearning tutorial(6)易用的深度学习框架Keras简介
    查看>>
    DeepLearning tutorial(7)深度学习框架Keras的使用-进阶
    查看>>
    流形学习-高维数据的降维与可视化
    查看>>
    Python-OpenCV人脸检测(代码)
    查看>>
    python+opencv之视频人脸识别
    查看>>
    人脸识别(OpenCV+Python)
    查看>>
    6个强大的AngularJS扩展应用
    查看>>
    网站用户登录系统设计——jsGen实现版
    查看>>
    第三方SDK:讯飞语音听写
    查看>>
    第三方SDK:JPush SDK Eclipse
    查看>>
    第三方开源库:imageLoader的使用
    查看>>
    自定义控件:飞入飞出的效果
    查看>>
    自定义控件:动态获取控件的高
    查看>>
    第三方开源库:nineoldandroid:ValueAnimator 动态设置textview的高
    查看>>
    第三方SDK:百度地图SDK的使用
    查看>>