web前端-在迷惘中的探索HTML5(三)文件操作FileReader

簡(jiǎn)介

在HTML5中,文件選擇標(biāo)簽file增加了如下兩個(gè)屬性:

  • multiple:設(shè)定當(dāng)前元素可以選取多個(gè)文件。
  • accept:設(shè)定當(dāng)前選擇器可以選擇的MIME類型或后綴名。
<input type="file" multiple name="" id="myfilePhoto" value="" accept="image/jpg, image/png">

于此同時(shí),其出現(xiàn)了FileReader對(duì)象,使用FileReader對(duì)象,web應(yīng)用程序可以異步的讀取存儲(chǔ)在用戶計(jì)算機(jī)上的文件(或者原始數(shù)據(jù)緩沖)內(nèi)容,可以使用File對(duì)象或者Blob對(duì)象來(lái)指定所要處理的文件或數(shù)據(jù)。

FileReader:是window對(duì)象的一個(gè)構(gòu)造函數(shù),用于讀取文件選擇標(biāo)簽選擇的File的Dom對(duì)象。即用來(lái)把文件選擇的信息讀入內(nèi)存,并且讀取文件中的數(shù)據(jù)。其接口提供了一個(gè)異步API,使用該API可以在瀏覽器主線程中異步訪問(wèn)文件系統(tǒng),讀取文件中的數(shù)據(jù)。為了安全FileReader可以讀取表單上已經(jīng)選擇的文件,不能讀取本地文件,它以二進(jìn)制信息的方式讀取表單文件:主要用于大文件的信息讀取。

特點(diǎn):

  1. 讀取后,二進(jìn)制信息在瀏覽器內(nèi)存中,批量的向服務(wù)器進(jìn)行傳輸。
  1. 一般要配合后臺(tái)程序,第三方插件共同完成
  2. 斷點(diǎn)下載和斷點(diǎn)上傳

使用介紹

創(chuàng)建FileReader對(duì)象

想要?jiǎng)?chuàng)建一個(gè)FileReader對(duì)象,很簡(jiǎn)單,如下:

var fr = new FileReader();
FileReader的狀態(tài)常量:

|常量名 | 值 | 描述
|-
|EMPTY | 0 | 還沒(méi)有加載任何數(shù)據(jù).
|LOADING | 1 | 數(shù)據(jù)正在被加載.
|DONE | 2 | 已完成全部的讀取請(qǐng)求.

FileReader接口的方法

FileReader接口有5個(gè)方法,其中4個(gè)用來(lái)讀取文件,另一個(gè)用來(lái)中斷讀取。無(wú)論讀取成功或失敗,方法并不會(huì)直接返回讀取結(jié)果,這一結(jié)果存儲(chǔ)在result屬性中。

FileReader接口的方法:

|方法名 | 參數(shù) | 描述
|-
|readAsArrayBuffer | file | 將文件讀取為一個(gè)ArrayBuffer對(duì)象以表示所讀取文件的內(nèi)容.
|readAsBinaryString | file | 將文件讀取為二進(jìn)制編碼
|readAsText | file,[encoding] | 將文件讀取為文本
|readAsDataURL | file | 將文件讀取為DataURL,讀取的內(nèi)容是加密以后的本地文件路徑
|abort | (none) | 終端讀取操作

FileReader的屬性:

|屬性名 | 類型 | 描述
|-
|error | DOMError | 在讀取文件時(shí)發(fā)生的錯(cuò)誤. 只讀.
|readyState | unsigned short | 表明FileReader對(duì)象的當(dāng)前狀態(tài). 值為State constants中的一個(gè). 只讀
|result | jsval | 讀取到的文件內(nèi)容.這個(gè)屬性只在讀取操作完成之后才有效,并且數(shù)據(jù)的格式取決于讀取操作是由哪個(gè)方法發(fā)起的. 只讀.

FileReader接口事件

FileReader接口包含了一套完整的事件模型,用于捕獲讀取文件時(shí)的狀態(tài)。

FileReader接口的事件:

|事件 | 描述
|-
|onabort | 中斷
|onerror | 出錯(cuò)
|onloadstart | 開(kāi)始
|onprogress | 正在讀取
|onload | 成功讀取
|onloadend | 讀取完成,無(wú)論成功失敗

實(shí)例說(shuō)明一切:

講完這些大家其實(shí)還是不知道怎么用,于是,實(shí)例來(lái)說(shuō)明一切:

<!-- multiple多個(gè)文件 -->
<input type="file" multiple name="" id="myfilePhoto" value="" accept="image/jpg, image/png">
<ul class="fileUl"></ul>
<script>
    document.getElementById('myfilePhoto').addEventListener("change",function(){
        var inputFile = document.getElementById('myfilePhoto');
        for(var i = 0; i<inputFile.files.length ;i++){
            var fr = new FileReader(); // 這個(gè)FileReader應(yīng)該對(duì)應(yīng)于每一個(gè)讀取的文件都需要重新new一個(gè)
            var files = inputFile.files[i]; // files可以獲取當(dāng)前文件輸入框中選擇的所有文件,返回列表
            fr.readAsDataURL(files); // 讀取的內(nèi)容是加密以后的本地文件路徑
            fr.onload = function(e){ // 數(shù)據(jù)讀取完成時(shí)觸發(fā)onload對(duì)應(yīng)的響應(yīng)函數(shù)
                // e.target是FileReader等同于fr
                var ulLi = document.createElement('li');
                var ulLiA = document.createElement('a');
                var ulLiimg = document.createElement('img');
                ulLiimg.src = e.target.result
                ulLiA.appendChild(ulLiimg);
                ulLi.appendChild(ulLiA);
                console.log(document.getElementsByClassName('fileUl'))
                document.getElementsByClassName('fileUl')[0].appendChild(ulLi)
            }       
        }
    });
</script>
<script>
    function updateSize() {
        var nBytes = 0;
        var oFiles = document.getElementById("uploadInput").files;
        var nFiles = oFiles.length;
        for (var nFileId = 0; nFileId < nFiles; nFileId++) {
            nBytes += oFiles[nFileId].size;
        }
        var sOutput = nBytes + " bytes";
        var aMultiples = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
        var nMultiple = 0, nApprox = nBytes / 1024;

        for ( ; nApprox > 1; nApprox /= 1024, nMultiple++) {
            sOutput = nApprox.toFixed(3) + " " + aMultiples[nMultiple] + " (" + nBytes + " bytes)";
        }

        document.getElementById("fileNum").innerHTML = nFiles;
        document.getElementById("fileSize").innerHTML = sOutput;
    }
</script>
<p>
    <input id="uploadInput" type="file" name="myFiles" onchange="updateSize();" multiple>
    選擇的文件數(shù):<span id="fileNum">0</span>
    總共大小:<span id="fileSize">0</span>
</p>

注意:在遍歷時(shí)把 var fileReader = new FileReader(); 放到了循環(huán)之外,會(huì)導(dǎo)致了 Uncaught InvalidStateError: Failed to execute 'readAsDataURL' on 'FileReader': The object is already busy reading Blobs.錯(cuò)誤,這個(gè)FileReader應(yīng)該對(duì)應(yīng)于每一個(gè)讀取的文件都需要重新new一個(gè)。
onload只在所有數(shù)據(jù)讀取成功完成時(shí)觸發(fā),并且結(jié)果也只在onload之后才有。
問(wèn)題解釋:因?yàn)槟忝看窝h(huán)如果只new了一次相當(dāng)與你只創(chuàng)建一個(gè)fileReader對(duì)象,可是我們每次循環(huán)時(shí),拿到的文件信息卻是不同的,這就好比你雇了一個(gè)員工,要求他同時(shí)去打掃衛(wèi)生間又打掃辦公室又去澆花,他只能先干完一件才能去干另一件,所以它就會(huì)給你報(bào)錯(cuò):The object is already busy reading Blobs.對(duì)象已經(jīng)在忙著閱讀Blobs-即忙著處理不可變的類似文件對(duì)象的原始數(shù)據(jù)。你一定會(huì)疑問(wèn)我是for循環(huán)一次完成了???你別忘了fr.onload是一個(gè)異步的,你for一次完成,但是處理信息并沒(méi)有完成,這就是你指揮員工命令已完成,但是,員工干活卻還在干,因?yàn)楦苫钜彩且獣r(shí)間的。

FileReader接口的使用

實(shí)例結(jié)束再來(lái)個(gè)大點(diǎn)案例:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script type="text/javascript">  
        var result=document.getElementById("result");  
        var file=document.getElementById("file");  
          
        //判斷瀏覽器是否支持FileReader接口  
        if(typeof FileReader == 'undefined'){  
            result.InnerHTML="<p>你的瀏覽器不支持FileReader接口!</p>";  
            //使選擇控件不可操作  
            file.setAttribute("disabled","disabled");  
        }  
          
        function readAsDataURL(){  
            //檢驗(yàn)是否為圖像文件  
            var file = document.getElementById("file").files[0];  
            if(!/image\/\w+/.test(file.type)){  
                alert("看清楚,這個(gè)需要圖片!");  
                return false;  
            }  
            var reader = new FileReader();  
            //將文件以Data URL形式讀入頁(yè)面  
            reader.readAsDataURL(file);  
            reader.onload=function(e){  
                var result=document.getElementById("result");  
                //顯示文件  
                result.innerHTML='![](' + this.result +')';  
            }  
        }  
          
        function readAsBinaryString(){  
            var file = document.getElementById("file").files[0];  
            var reader = new FileReader();  
            //將文件以二進(jìn)制形式讀入頁(yè)面  
            reader.readAsBinaryString(file);  
            reader.onload=function(f){  
                var result=document.getElementById("result");  
                //顯示文件  
                result.innerHTML=this.result;  
            }  
        }  
          
        function readAsText(){  
            var file = document.getElementById("file").files[0];  
            var reader = new FileReader();  
            //將文件以文本形式讀入頁(yè)面  
            reader.readAsText(file);  
            reader.onload=function(f){  
                var result=document.getElementById("result");  
                //顯示文件  
                result.innerHTML=this.result;  
            }  
        }  
    </script>  
    <p>  
        <label>請(qǐng)選擇一個(gè)文件:</label>  
        <input type="file" id="file" />  
        <input type="button" value="讀取圖像" onclick="readAsDataURL()" />  
        <input type="button" value="讀取二進(jìn)制數(shù)據(jù)" onclick="readAsBinaryString()" />  
        <input type="button" value="讀取文本文件" onclick="readAsText()" />  
    </p>  
    <div id="result" name="result"></div>
</body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容