HTML5之FileReader读取文件

HTML5之FileReader接口读取文件

minsong
minsong 发布于 2016-05-09 17:57:46  浏览: 8402  类型: 原创 - 随笔  分类: HTML/CSS - HTML5  二维码:   作者原创 版权保护
HTML5之FileReader读取文件

    用来把文件读入内存,并且读取文件中的数据。FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据。到目前为止,只有FF3.6+和Chrome6.0+实现了FileReader接口。

1.FileReader接口的方法

FileReader接口有4个方法,其中3个用来读取文件,另一个用来中断读取。无论读取成功或失败,方法并不会返回读取结果,这一结果存储在result属性中。

方法名                                                参数                                                                     描述
readAsBinaryString                                 file                                                       将文件读取为二进制编码
readAsText                                 file,[encoding]                  将文件读取为文本,其中第二个参数是文本的编码方式,默认值为 UTF-8
readAsDataURL                                 file                                                      将文件读取为DataURL
abort                                              (none)                                                    终端读取操作


2.FileReader接口事件


FileReader接口包含了一套完整的事件模型,用于捕获读取文件时的状态。

   事件                              描述
onabort                               中断
onerror                              出错
onloadstart                     开始
onprogress                 正在读取
onload                        成功读取
onloadend        读取完成,无论成功失败



3.FileReader接口的使用


文件一旦开始读取,无论成功或失败,实例的 result 属性都会被填充。如果读取失败,则 result 的值为 null ,否则即是读取的结果,绝大多数的程序都会在成功读取文件的时候,抓取这个值。

var reader=new FileReader();
reader.onload = function() {  
                    this.result;  
};  
//
var reader=new FileReader();
reader.onload = function(e) {  
                    e.target.result;  
};  

例子1:

    
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<! DOCTYPE   HTML >
< html >
< head >
< meta   http-equiv = "Content-Type"   content = "text/html; charset=utf-8" >
< title > </ title >
< style >
img {
     width: 100 px;
     height: 100 px;
}
</ style >
</ head >
< body >
< script   type = "text/javascript" >
if ( typeof  FileReader  ==  'undefined' ) {    //FileReader  
     var  div = document . getElementById ( "dd" ) ;
     div . innerHTML = 'FileReader' ;
     document . getElementById ( "file" ) . setAttribute ( "disabled" , "disabled" ) ;
     document . getElementById ( "filea" ) . setAttribute ( "disabled" , "disabled" ) ;
     document . getElementById ( "fileb" ) . setAttribute ( "disabled" , "disabled" ) ;
}
function  show ( ) {
     var  file = document . getElementById ( "file" ) . files [ 0 ] ;
     var  reg = /image \/\w + / ;
     if ( ! reg . test ( file . type )) {    //
         return  false ;
     }
     if ( file ) {
         var  reader  =  new  FileReader ( ) ;
         reader . onload  =  function  (   event   )  {
              var  txt  =  event . target . result ;
              var  img  =  document . createElement ( "img" ) ;
              img . src  =  txt ;
              document . getElementById ( "content" ) . appendChild (  img  ) ;
         }
     }
     reader . readAsDataURL ( file ) ;
} 
function  aShow ( ) {
     var  file = document . getElementById ( "filea" ) . files [ 0 ] ;
     if ( file ) {
         var  reader = new  FileReader ( ) ;
         reader . onload = function ( ) {
              var  cona = document . getElementById ( "contenta" ) ;
              cona . innerHTML = this . result ;
         }
     }
     reader . readAsBinaryString ( file ) ;
}
function  bShow ( ) {
     var  file = document . getElementById ( "fileb" ) . files [ 0 ] ;
     if ( file ) {
         var  reader = new  FileReader ( ) ;
         reader . onload = function ( e ) {
              var  conb = document . getElementById ( "contentb" ) ;
              conb . innerHTML = e . target . result ;
         }
     }
     reader . readAsText ( file ) ;
}
</ script >  
< div   id = "dd" >   </ div >
< p > < input   type = "file"   name = "file"   id = 'file'   onchange = 'show()' /> </ p >
< p   id = 'content' > </ p >
< p > < input   type = "file"   name = "file"   id = 'filea'   onchange = 'aShow()' /> </ p >
< p   id = 'contenta' > </ p >
< p > < input   type = "file"   name = "file"   id = 'fileb'   onchange = 'bShow()' /> </ p >
< p   id = 'contentb' > </ p >
</ body >
</ html >


例子2:兼容IE的上传图片

    
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<! DOCTYPE   html   PUBLIC   "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
< html   xmlns = "http://www.w3.org/1999/xhtml" >
< head >      
< meta   http-equiv = "Content-Type"   content = "text/html; charset=utf-8"   />      
< title > </ title >      
< style   type = "text/css" >
#preview { width: 547 px; height: 626 px; border: 1 px  solid  #000; overflow: hidden; }
#imghead  {filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=image); }
input { margin-top: 20 px; }
</ style >
< script   type = "text/javascript" >
                   //    IE
         function  previewImage ( file )
         {
            var  MAXWIDTH   =  547 ; 
            var  MAXHEIGHT  =  626 ;
            var  div  =  document . getElementById ( 'preview' ) ;
            if  ( file . files  &&  file . files [ 0 ])
            {
                 div . innerHTML  = '<img id=imghead>' ;
                 var  img  =  document . getElementById ( 'imghead' ) ;
                 img . onload  =  function ( ) {
                   var  rect  =  clacImgZoomParam ( MAXWIDTH ,  MAXHEIGHT ,  img . offsetWidth ,  img . offsetHeight ) ;
                   img . width   =   rect . width ;
                   img . height  =   rect . height ;
//                 img.style.marginLeft = rect.left+'px';
                   img . style . marginTop  =  rect . top + 'px' ;
                 }
                 var  reader  =  new  FileReader ( ) ;
                 reader . onload  =  function ( evt ) { img . src  =  evt . target . result ; }
                 reader . readAsDataURL ( file . files [ 0 ]) ;
            }
            else  //IE
            {
              var  sFilter = 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale,src="' ;
              file . select ( ) ;
              var  src  =  document . selection . createRange ( ) . text ;
              div . innerHTML  =  '<img id=imghead>' ;
              var  img  =  document . getElementById ( 'imghead' ) ;
              img . filters . item ( 'DXImageTransform.Microsoft.AlphaImageLoader' ) . src  =  src ;
              var  rect  =  clacImgZoomParam ( MAXWIDTH ,  MAXHEIGHT ,  img . offsetWidth ,  img . offsetHeight ) ;
              status  = ( 'rect:' + rect . top + ',' + rect . left + ',' + rect . width + ',' + rect . height ) ;
              div . innerHTML  =  "<div id=divhead style='width:" + rect . width + "px;height:" + rect . height + "px;margin-top:" + rect . top + "px;" + sFilter + src + " \" '></div>" ;
            }
         }
         function  clacImgZoomParam (   maxWidth maxHeight width height   ) {
              var  param  =  { top : 0 ,  left : 0 ,  width : width ,  height : height } ;
              if (  width > maxWidth  ||  height > maxHeight  )
              {
                   rateWidth  =  width  /  maxWidth ;
                   rateHeight  =  height  /  maxHeight ;
                  
                   if (  rateWidth  >  rateHeight  )
                   {
                        param . width  =   maxWidth ;
                        param . height  =  Math . round ( height  /  rateWidth ) ;
                   } else
                   {
                        param . width  =  Math . round ( width  /  rateHeight ) ;
                        param . height  =  maxHeight ;
                   }
              }
             
              param . left  =  Math . round (( maxWidth  -  param . width )  /  2 ) ;
              param . top  =  Math . round (( maxHeight  -  param . height )  /  2 ) ;
              return  param ;
         }
</ script >      
</ head >      
< body >
      
     < input   type = "file"   onchange = "previewImage(this)"   />   
     < div   id = "preview" >
          < img   id = "imghead"   src = '' >
     </ div >    
</ body >      
</ html >


示例3:有上传进度条
既然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的进度条。

    
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<! DOCTYPE   HTML >
< html >
< head >
< meta   http-equiv = "Content-Type"   content = "text/html; charset=utf-8" >
< title > </ title >
</ head >
< body >
< form >   
     < fieldset >   
          < legend > </ legend >   
          < input   type = "file"   id = "file"   />   
          < input   type = "button"   value = ""   id = "Abort"   />   
          < p >   
               < label > </ label > < progress   id = "Progress"   value = "0"   max = "100" > </ progress >   
          </ p >   
          < p   id = "Status" > </ p >   
     </ fieldset >   
</ form >   
< script >
     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 ( ) ;  
</ script >
</ body >
</ html >


    
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
< form >
     < fieldset >
          < legend > </ legend >
          < input   type = "file"   id = "File"   />
          < input   type = "button"   value = ""   id = "Abort"   />
          < p >
               < label > </ label > < progress   id = "Progress"   value = "0"   max = "100" > </ progress >
          </ p >
          < p   id = "Status" > </ p >
     </ fieldset >
</ form >
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();


4.预览文本文件

     这里主要用到FileReader的readAsText,对于诸如mimetype为text/plain、text/html等文件均认为是文本文件,即minetype为text开头都能在本例中预览。
     由于需要在页面上预览文本,如果使用innerHTML插入文本的话,则需要对html中一些特殊字符进行实体编码,这样才能保证正常显示文本。
    encodeHTML方法:

    
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
function encodeHTML(source) {
    return source
              .replace(/&/g, '&')
              .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 = ' < li > ' + f.name +'. </ li > ';
                
              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');
}


5、分段读取文件内容(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。
        

    
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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!')
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值