HTML5之fileReader異步讀取文件及文件切片讀取

  • fileReader的方法與事件
  • fileReade實現圖片預加載
  • fileReade實現文件讀取進度條
  • fileReade的與file.s實現文件切片讀取

 1、fileReader的方法與事件

1.方法

  • FileReader.abort():終止讀取操做。返回時,readyState屬性爲DONE。
  • FileReader.readAsArrayBuffer():將文件讀取爲ArrayBuffer數據對象。
  • FileReader.readAsBinaryString():將文件讀取爲二進制數據。
  • FileReader.readAsDataURL():將文件讀取爲DataURL編碼(base64)==>URL格式的字符串。
  • FileReader.readAsText():將文件讀取爲文本==》字符串表示的文件內容。

2.事件

  • FileReader.onloadstart:讀取開始時觸發
  • FileReader.onprogress:讀取中
  • FileReader.onloadend:讀取完成觸發,不管成功或失敗
  • FileReader.onload:文件讀取成功完成時觸發
  • FileReader.onabort:中斷時觸發
  • FileReader.onerror:出錯時觸發

3.實現圖片讀取預覽

在Web FileReader API接口實現以前,圖片預覽的一般作法是先將圖片上傳至服務器,上傳成功之後經過過觸發ajax請求到剛剛上傳的圖片,而後加載到頁面。這個過程當中若是圖片選擇錯誤或者須要修改上傳的圖片,就須要重複上傳和下載請求,而且還須要在服務器替換圖片資源,會浪費大量的網絡資源和服務器資源。如今經過FileReader實現本地圖片讀取預覽,就能夠在本地實現圖片修改,節省服務器資源。css

既然是HTML5的API就目前來講確定存在兼容性問題,目前IE10開始支持FileReader,因此經過服務上傳下載的圖片預覽方式仍是有必要的,接下來的示例僅僅展現FileReader的圖片讀取預覽代碼:html

 1 <style>
 2     .imgBox{
 3         display: flex;
 4         width: 300px;
 5         height: 300px;
 6         border: 1px solid #300;
 7         justify-content: center;
 8         align-items: center;
 9     }
10 </style>
11 <input type="file" name="">
12 <div class="imgBox"></div>
13 <script>
14     var imgBox = document.getElementsByClassName('imgBox')[0];
15     var reader = new FileReader(); //建立文件讀取對象
16     var inp = document.getElementsByTagName('input')[0]; //獲取文件源
17     inp.onchange = function(){ //input域發生改變後觸發文件讀取
18         reader.readAsDataURL(inp.files[0]); //使用文件讀取對象讀取圖片爲base64編碼
19     }
20     reader.onload = function(e){ //當圖片讀取成功後觸發
21         var img = new Image(); //建立img對象
22         img.src = e.target.result; //給img對象添加緩存中的bese64位編碼的圖片數據(異步)
23         img.onload = function(e){ //圖片數據加載完成之後
24             if(this.width > this.height){ //當圖片的寬度大於高度
25                 img.style.width = '100%'; //是:設置圖片寬度100%,實現圖片所有預覽
26             }else{
27                 img.style.height = '100%';//否:設置圖片高度100%,實現圖片所有預覽
28             }
29             imgBox.style.backgroundColor = '#000';
30             imgBox.innerHTML = null;
31             imgBox.appendChild(img);
32         }
33     }
34 </script>

4.實現文件加載進度條

在FileReader.onprogress事件對象中有兩個屬性loaded和total,loaded表示當前文件讀取大小,total表示文件總體大小,而且在讀取時會持續觸發更新最新讀取狀態的數據,根據FileReader.onprogress事件就能夠實現文件加載進度條的動畫效果了,可是因爲FileReader是h5的API在IE中最低兼容到10版本,因此須要根據具體的項目和兼容性來設計交互。web

 1 //css
 2 .progress{
 3     position: relative;
 4     margin-top: 5px;
 5     width: 300px;
 6     height: 20px;
 7     border: 1px solid #300;
 8 }
 9 .progressText{
10     display: inline-block;
11     position: absolute;
12     width: 300px;
13     height: 20px;
14     text-align: center;
15     font-size: 10px;
16     line-height: 20px;
17 }
18 .progressSpan{
19     display: inline-block;
20     /* width: 200px; */
21     height: 20px;
22     background-color: #f0f;
23 }
24 //html
25 <input type="file" name="">
26 <!-- 文件加載進度條 -->
27 <div class="progress">
28     <span class="progressText"></span>
29     <span class="progressSpan"></span>
30 </div>
31 //js
32 //獲取文件源(全部功能實現的公共代碼區)
33 var inp = document.getElementsByTagName('input')[0]; //獲取文件源
34 var reader = new FileReader(); //建立文件讀取對象
35 // fileReader實現圖片加載進度條
36 var progressSpanObj = document.getElementsByClassName('progressSpan')[0];
37 var progressTextObj = document.getElementsByClassName('progressText')[0];
38 inp.onchange = function(){
39     reader.readAsArrayBuffer(inp.files[0]);
40 }
41 reader.onloadstart = function(e){ //開始讀取文件時觸發
42     progressTextObj.innerText = "正在讀取文件(0%)...";
43 }
44 reader.onprogress = function(e){ //讀取進度事件
45     console.log(Math.round(e.loaded / e.total * 100));
46     var precent = Math.round(e.loaded / e.total * 100);
47     progressSpanObj.style.width = precent / 100 * 300 + 'px';
48     progressTextObj.innerText = '正在讀取文件(' + precent + '%)...';
49 }
50 reader.onload = function(e){
51     progressTextObj.innerText = '文件讀取完成(100%)';
52 }
53 reader.onerror = function(e){
54     progressTextObj.innerText = "文件讀取出錯誤(~0v0~)";
55 }

 2、fileReade的與file.slice實現文件切片讀取

 經過input-type[file]獲取的文件對象上有這樣幾個數據:ajax

inputDom.files[0];//獲取File對象(在onchange事件後獲取)

File對象上的屬性與方法:

  • File():構造函數,返回一個新的文件對象
  • File.lastModified:返回所引用文件最後的修改日期,爲自 1970年1月1日0:00 以來的毫秒數。沒有已知的最後修改時間則會返回當前時間。
  • File.lastModifiedDate:返回當前File對象所引用文件最後修改事件的Date都西昂。
  • File.name:返回當前File對象所引用文件的名字。
  • File.size:返回文件的大小
  • File.webkitRelativePath:返回Filex相關的path或URL(這是個非標準屬性,chrome上獲取的是一個空字符串)
  • File.slice():文件對象上自己是沒有方法的,slice方法同經過繼承Blob對象上的slice方法實現的。

File對象說明手冊(MDN):https://developer.mozilla.org/zh-CN/docs/Web/API/Filechrome

File.slice()方法說明手冊(MDN):https://developer.mozilla.org/zh-CN/docs/Web/API/Blob/slice緩存

File.slice實現文件切片讀取:

 1 <!--樣式同上面的進度條實例同樣,這裏就不添加了-->
 2 <input type="file" name="">
 3 <!-- 文件加載進度條 -->
 4 <div class="progress">
 5     <span class="progressText"></span>
 6     <span class="progressSpan"></span>
 7 </div>
 8 //獲取文件源(全部功能實現的公共代碼區)
 9 var inp = document.getElementsByTagName('input')[0]; //獲取文件源
10 var reader = new FileReader(); //建立文件讀取對象
11 // fileReader實現圖片加載進度條
12 var progressSpanObj = document.getElementsByClassName('progressSpan')[0];
13 var progressTextObj = document.getElementsByClassName('progressText')[0];
14 //file.slice(起始字節,終止字節)與FileReader實現文件切片讀取
15 function PartFileReader(files,type,event){
16     this.files = files;//inputObj.files[0]
17     this.type = type;  //配置FileReader讀取文件的方法
18     this.event = event;//配置讀取文件時須要觸發的事件
19     this.total = files.size;//獲取文件大小
20     this.step = 1024 * 1024;//1MB(單片大小/一兆)
21     this.loaded = 0; //文件當前讀取進度
22     this.reader = new FileReader(); //實際讀取文件的FileReader對象實例
23     this.abort = this.reader.abort; //中斷文件讀取(能夠經過中斷文件讀取事件保留切片數據,實現下一次能夠在原讀取位置繼續開始讀取)
24     this.readPartFile(this.loaded); //開啓讀取文件
25     this.bindEvent();//綁定FileReader文件讀取
26 }
27 //給切片讀取對象原型上添加FileReader獲取讀取類型,開啓讀取文件
28 PartFileReader.prototype.readPartFile = function(start){
29     if(this.files.slice){
30         var file = this.files.slice(start,this.loaded + this.step);
31         switch(this.type){
32             case 'readAsBinaryString' :
33                 this.reader.readAsBinaryString(file);
34                 break;
35             case 'readAsDataURL' :
36                 this.reader.readAsDataURL(file);
37                 break;
38             case 'readAsArrayBuffer' :
39                 this.reader.readAsArrayBuffer(file);
40                 break;
41             case 'readAsText' :
42                 this.readAsText(file);
43                 break;
44         }
45     }
46 }
47 //給切片讀取對象原型上綁定FileReader對象事件
48 PartFileReader.prototype.bindEvent = function(){
49     var self = this;
50     this.reader.onloadstart = function(e){
51         self.event.loadStart && self.event.loadStart.call(this,e);
52     }
53     this.reader.onprogress = function(e){
54         self.event.progress && self.event.progress.call(this,e);
55     }
56     this.reader.onload = function(e){
57         // 切片讀取文件有別於非切片讀取,切片讀取的文件讀取狀態須要在每一個切片讀取成功後再刷新讀取進度
58         self.loaded += e.loaded;
59         self.event.load && self.event.load.call(this,e,self.loaded,self.total);
60         if(self.loaded < self.total){
61             self.readPartFile(self.loaded);
62         }
63     }
64     this.reader.onloadend = function(e){
65         self.event.loadend && self.event.loadend.call(this,e);
66     }
67     this.reader.onabort = function(e){
68         self.event.abort && self.event.abort.call(this,e);
69     }
70 }
71 //調用文件切片讀取對象,配置FileReader事件函數
72 inp.onchange = function(){
73     var reader = new PartFileReader(inp.files[0],'readAsArrayBuffer',{
74         loadStart:function(e){
75             progressTextObj.innerText = "正在讀取文件(0%)...";
76         },
77         progress:function(e){},
78         load:function(e,loaded,total){
79             // 若是在讀取的基礎上寫上傳的話在這裏獲取讀取成功的文件切片
80             // e.target.result //當前文件切片的數據
81             // (可是千萬別在這裏直接寫網絡請求,本地讀取的速度遠遠大於網絡請求,直接請求一個文件就會在瞬間發起大量請求)
82             // (最好的處理方式是將切片數據寫入一個有序列表中,而後經過控制網絡請求數量來實現)
83             var precent = Math.round(loaded / total * 100);
84             progressSpanObj.style.width = precent / 100 * 300 + 'px';
85             if(precent < 100){
86                 progressTextObj.innerText = '正在讀取文件(' + precent + '%)...';
87             }else if(precent == 100){
88                 progressTextObj.innerText = '文件讀取完成(100%)';
89             }
90         },
91         loadend:function(e){},
92         abort:function(e){},
93         error:function(e){
94             progressTextObj.innerText = "文件讀取出錯誤(~0v0~)";
95         }
96     })
97 }
相關文章
相關標籤/搜索