HTML5定義了FileReader作為檔案API的重要成員用於讀取檔案,根據W3C的定義,FileReader介面提供了讀取檔案的方法和包含讀取結果的事件模型。
FileReader的使用方式非常簡單,可以按照如下步驟建立FileReader物件並呼叫其方法:
1.檢測瀏覽器對FileReader的支援
if(window.FileReader) { var fr = new FileReader(); // add your code here } else { alert("Not supported by your browser!"); }
2. 呼叫FileReader物件的方法
FileReader 的例項擁有 4 個方法,其中 3 個用以讀取檔案,另一個用來中斷讀取。下面的表格列出了這些方法以及他們的引數和功能,需要注意的是 ,無論讀取成功或失敗,方法並不會返回讀取結果,這一結果儲存在 result屬性中。
方法名 | 引數 | 描述 |
---|---|---|
abort | none | 中斷讀取 |
readAsBinaryString | file | 將檔案讀取為二進位制碼 |
readAsDataURL | file | 將檔案讀取為 DataURL |
readAsText | file, [encoding] | 將檔案讀取為文字 |
readAsText:該方法有兩個引數,其中第二個引數是文字的編碼方式,預設值為 UTF-8。這個方法非常容易理解,將檔案以文字方式讀取,讀取的結果即是這個文字檔案中的內容。
readAsBinaryString:該方法將檔案讀取為二進位制字串,通常我們將它傳送到後端,後端可以通過這段字串儲存檔案。
readAsDataURL:這是例子程式中用到的方法,該方法將檔案讀取為一段以 data: 開頭的字串,這段字串的實質就是 Data URL,Data URL是一種將小檔案直接嵌入文件的方案。這裡的小檔案通常是指影像與 html 等格式的檔案。
3. 處理事件
FileReader 包含了一套完整的事件模型,用於捕獲讀取檔案時的狀態,下面這個表格歸納了這些事件。
事件 | 描述 |
---|---|
onabort | 中斷時觸發 |
onerror | 出錯時觸發 |
onload | 檔案讀取成功完成時觸發 |
onloadend | 讀取完成觸發,無論成功或失敗 |
onloadstart | 讀取開始時觸發 |
onprogress | 讀取中 |
檔案一旦開始讀取,無論成功或失敗,例項的 result 屬性都會被填充。如果讀取失敗,則 result 的值為 null ,否則即是讀取的結果,絕大多數的程式都會在成功讀取檔案的時候,抓取這個值。
fr.onload = function() { this.result; };
下面通過一個上傳圖片預覽和帶進度條上傳來展示FileReader的使用。
<script type="text/javascript"> function showPreview(source) { var file = source.files[0]; if(window.FileReader) { var fr = new FileReader(); fr.onloadend = function(e) { document.getElementById("portrait").src = e.target.result; }; fr.readAsDataURL(file); } } </script> <input type="file" name="file" onchange="showPreview(this)" /> <img id="portrait" src="" width="70" height="75">
如果要限定上傳檔案的型別,可以通過檔案選擇器獲取檔案物件並通過type屬性來檢查檔案型別
if(!/image\/\w+/.test(file.type)){ alert("請確保檔案為影像型別"); return false; }
不難發現這個檢測是基於正規表示式的,因此可以進行各種複雜的匹配,非常有用。
如果要增加一個進度條,可以使用HTML 5的progress標籤,通過下面的程式碼實現。
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();