1. 程式人生 > >前端學習(八十三) DOM-檔案(Dom)

前端學習(八十三) DOM-檔案(Dom)

File物件

最常見的功能就是頭像上傳,檔案預覽,檔案上傳這些類似的功能

input上的type='file',就可以實現選擇檔案功能

先看一個示例

        <div class="div-a">
            <input type="file" id="file" class="div-input">
            <div class="div-b" id="upfile"></div>
        </div>
        <input type="button" value="上傳" id="btn">
        <script>
            let divB=document.getElementById('upfile'),
                fileS=document.getElementById('file'),
                btn=document.getElementById('btn');
            let a=undefined;
            fileS.addEventListener('change',function (params) {
                // console.log(params.target.files);
                a=params.target.files;  //params.target.files獲得的是一個類陣列flieList物件,有length屬性
            })
            btn.addEventListener('click',function(params){
                if(a===undefined){
                    console.log('尚未選擇檔案');
                }
                else{
                    //非同步上傳檔案
                    //console.log(a[0]);  
                    let fd=new FormData();
                    fd.append('file',a[0], a[0].name);
                    let xhr=new XMLHttpRequest();
                    xhr.open('POST','伺服器地址');
                    xhr.send()
                }
            })
        </script>

其中a[0]獲得的就是類似於:File(2554) {name: "changelog.txt", lastModified: 1477137622000, lastModifiedDate: Sat Oct 22 2016 20:00:22 GMT+0800 (中國標準時間), webkitRelativePath: "", size: 2554, …}

這邊就是定了一個input為file,但是實際開發中不會直接使用這種樣式,因此這邊簡單的修飾了一下,將file因此,在file的下面疊加了一個樣式div,選擇檔案後將目標檔案的files屬性賦值給a,點選上傳後將a上傳至伺服器

 

File物件的屬性(只讀)

屬性 說明
lastModified 檔案的最近修改時間,從1970年開始的間隔時間
lastModifiedDate 檔案的最近修改日期,已經不推薦使用
name 檔名
webkitRelativePath 相對於使用者所選擇的資料夾路徑
size 檔案大小,單位是位元組
type 檔案的MIME型別,比如Image/jpeg

Flie物件的方法

File物件本身沒有任何方法,但是Flie物件繼承自Blob,Blob有一個方法

Blob.slice([start[,end[,contentType]]])

 

和File結合使用的物件

FlileList

FileList,可以通過input元素的files屬性獲得,或者通過Drag和Drop API獲取使用者拖入到網頁中的檔案列表

<input type='file' id='file' multiple>

加了multiple屬性後,使用者就可以加入多個檔案,這時候的FlieList就是一個類陣列的形式,從下標0開始

屬性/方法

屬性/方法 說明
length 包含的檔案個數,只讀
item() 根據索引引數,返回對應的檔案

Drag和Drop,拖拽事件

名稱 作用
dragstart 在拖動時觸發
dragend 在拖動完成時觸發
dragenter 目標元素上繫結dragenter事件,當拖拽元素進入目標元素時觸發
dragover 目標元素上繫結dragover事件, 當拖拽元素在目標元素上移動時觸發
drop 目標元素上繫結drop事件, 並同時取消當前目標元素的dragover的預設事件, 當拖拽元素在目標元素上同時滑鼠放開時觸發事件.
例: box為目標元素.
box.addEventListener('dragover', function(e){console.log('dragover'); e.preventDefault();});
box.addEventListener('drop', function(e){console.log('drop');});
dropdragend同時繫結時drop事件先觸發
            let drop = document.querySelector('.drop');
            drop.addEventListener('dragover',function (params) {    /*拖動到目標上方的事件*/
                params.preventDefault();    /*不要執行與事件關聯的預設動作*/
                drop.classList.add('over')
            });
            drop.addEventListener('drop',function (params) {    /*拖動到目標位置且鬆開觸發*/
                params.preventDefault();
                drop.classList.remove('over');
                console.log(params.dataTransfer.files); //  輸出了一個fileList
            })

 

FileReader

用來讀取檔案內容,讀取過程是非同步的,檔案就是FileList的屬性值

屬性(都是隻讀)

屬性 說明
error 讀檔案異常時的錯誤資訊
readyState FileReader的狀態,數值
result 檔案內容

當中關於readyState的取值

屬性 說明
FlileReader.EMPTY 0 尚未載入資料
FlieReader.LOADING 1 正在載入資料
FileReader.DONE 2 讀取請求已完成

物件的方法

屬性 說明
abort 終止讀取檔案
readAsArrayBuffer 讀取的檔案內容以ArrayBuffer的形式返回
readAsDataURL 讀取的檔案以data:URL的形式返回
readAsText 讀取的檔案內容以純文字的形式返回
readAsBinaryString(非標準) 讀取的檔案內容以原始二進位制文字的形式返回

物件的事件(也就是可監聽的事件)

事件 說明
onabort 終止讀取檔案時觸發
onerror 讀取異常時觸發
onload 去讀成功時觸發
onloadstart 開始讀取時觸發
onloadend 讀取完成(可能成功,也可能失敗)時觸發
onprogress 讀取過程中觸發

Blob

Blob,二進位制大物件,是binary large object 的縮寫,是用來儲存類似檔案的原始資料。

Blob建構函式

var aBlob=new Blob(array[,options])

  • array:陣列
  • option:目前納入規範的只有一個type,也就是型別

例如

            var af=['<a id="a"><div id="b"></div></a>']
            var aBlob=new Blob(af,{type:'text/html'})

方法

silce([start [,end [,contentType]]]):可以切割檔案內容,

  • start:起始索引
  • end:結束索引
  • contentType:指定型別

返回值也是一個blob物件,可以使用這個將大檔案分割成多個小檔案上傳,如果上傳中斷,下次上傳使用相同的方法,可以繼續上傳,但是前段頁面一般不用大檔案上傳,有很多侷限

URL

可以用來建立URL物件,也可以用來建立檔案物件的臨時地址,供使用者或開發者使用,比如本地圖片預覽等

let url=new URL(urlStr,[base])

  • urlStr:url字串
  • base:如果urlStr是一個相對地址,那麼可以指定它的相對目標地址

示例

            var url=new URL('../a','http://www.example.com/dogs')
            console.log(url.hostname);  //www.example.com
            console.log(url.pathname);  // /a

方法

方法 說明
URL.createObjectURL() 建立物件在瀏覽器中的臨時訪問地址
URL.revokeObjectURL() 回收使用createObjectURL方法建立的臨時訪問地址

createObjectURL(object)

接收的是一個引數,最常見的是flle或者Blob,返回的是一個可以在瀏覽器中訪問的地址,這個地址的生命週期是當前視窗,視窗關閉或者重新整理就無效了

revokeObjectURL(url)

引數就是建立的url地址,將其回收,節省瀏覽器的資源

示例:

            var obURL=URL.createObjectURL(object);
            URL.revokeObjectURL(obURL)

實際案例

限制檔案的型別

 <input type="file" id="file" class="div-input" accept="image/*">

只要將input中的設定accept屬性,就可以限制檔案型別(image/*是限制圖片型別),accpet接收的是mime型別,多個值以逗號分隔,比如“image/png,image/jpeg”,也可以寫檔案的字尾名“.png,.jpeg”,也支援萬用字元*,比如“image/*”

限制檔案大小,數量

<input type="file" id="file" class="div-input" accept="image/*" multiple>

只要拿到物件的fileList就可以判斷數量和大小

        <div class="div-a">
            <input type="file" id="file" class="div-input" accept="image/*" multiple>
            <div class="div-b" id="upfile"></div>
        </div>
        <input type="button" value="上傳" id="btn">
        <script>
            let divB=document.getElementById('upfile')
            fileS.addEventListener('change',function (params) {
                 if(a.length>3){
                        console.log('超出上限了');
                        fileS.value='';
                        return
                    }
                    let exceedSizeFiles=[].slice.call(a).filter(file=>{
                        return file.size > 10*1024;
                    })
                    if(exceedSizeFiles.length){
                        console.log("檔案最大為10KB");
                        
                    }
            })
        </script>

檔案按鈕美化

一種方法是將input隱藏,點選btn時,去關聯點選input

        <div class="div-a">
            <input type="file" id="file" class="div-input" accept="image/*" multiple>
            <div class="div-b" id="upfile"></div>
        </div>
        <input type="button" value="上傳" id="btn">
        <script>
            let divB=document.getElementById('upfile'),
                fileS=document.getElementById('file'),
                btn=document.getElementById('btn');
            fileS.addEventListener('change',function (params) {
              
            })
            btn.addEventListener('click',function(params){
                fileS.click();
            })
        </script>

另外一種是使用label,通過label的for去關聯input

        <div class="div-a">
            <label for="file">點選</label>
            <input type="file" id="file" class="div-input" accept="image/*" multiple>
        </div>
        <input type="button" value="上傳" id="btn">
        <script>
            let divB=document.getElementById('upfile'),
                fileS=document.getElementById('file');
            fileS.addEventListener('change',function (params) {
            })
        </script>

label的這種方法可以大大減少關聯程式碼

將文字內容顯示到網頁上

        <div class="div-a">
            <label for="file">點選</label>
            <input type="file" id="file" class="div-input" accept=".txt" >
        </div>
        <div id="text"></div>
        <script>
            let divB=document.getElementById('text'),
                fileS=document.getElementById('file');
            fileS.addEventListener('change',function (params) {
                var a=new ReadFile();
                a.read(params.target.files[0]);
            })
            function ReadFile(){
                //this.file=file
            }
            ReadFile.prototype={
                constructor:ReadFile,
                read:function(file) {
                    let fr=new FileReader();
                    fr.onload=function(e){
                        document.querySelector('#text').innerHTML = e.target.result;
                    }
                    fr.readAsText(file)
                }
            }
        </script>

將頁面上的文字建立文字檔案並下載

        <textarea id="textbox">此處輸入文字內容</textarea>
        <input type="button" id="create" value="建立文字">
        <a download="info.txt" id="downloadlink" style='display: none'>下載</a>
        <script>
            let textFile = null;
            let makeTextFile=function(text){
                let data= new Blob([text],{type:'text/plain'});
                if(textFile !== null){
                    window.URL.revokeObjectURL(textFile);
                }
                textFile = window.URL.createObjectURL(data);
                return textFile;
            }
            let create = document.getElementById("create");
            let textbox = document.getElementById('textbox');

            create.addEventListener('click',function (){
                let fileUrl = makeTextFile(textbox.value);
                let link = document.getElementById('downloadlink');
                link.href = fileUrl;
                link.click();
            })
        </script>

本地圖片預覽:FileReader.readAsDataURL

        <input type="file" id="file" accept="image/*">
        <script>
            let fileInput = document.querySelector('#file');
            fileInput.addEventListener('change',e=>{
                showImage(e.target.files[0])
            })
            function showImage(image) {
                let fr = new FileReader();
                fr.onload= function (params) {
                    let img = new Image();
                    img.src = params.target.result;
                    document.body.appendChild(img)
                }
                fr.readAsDataURL(image);
            }
        </script>