HTML5之FileReader的使用

品讀夜的黑發表於2016-04-12

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(); 

 

相關文章