前端必知必會之文件讀取、拖拽上傳

在前端開發中,拖拽上傳文件是一種很常見的需求。經過拖拽來實現文件上傳須要瞭解FileReader這個File API以及對應的拖拽事件前端

咱們先了解一下,在前端表單中是如何處理文件上傳的瀏覽器

files集合

一直以來,咱們都經過<input type='file'>字段來獲取文件的對應信息。HTML5爲文件輸入元素添加了一個files集合,在files集合中,有一組File對象,每一個File對象對應着一個文件bash

File對象屬性(只讀屬性):服務器

屬性 類型 描述
name 字符串 本地文件系統中的文件名
size 數字 文件的字節大小
type 字符串 文件的MIME類型
lastModifiedDate 字符串 文件上一次被修改的時間

具體的實現代碼以下:app

<input type='file' id='files'>
<script>
    var files = document.getElementById('files')
    files.addEventListener('change', function(event) {
        console.log(event.target.files)
        console.log(
            `文件名稱:${event.target.files[0].name}
             文件類型:${event.target.files[0].type}
             文件大小:${event.target.files[0].size} bytes`
             )
    })
</script>
複製代碼

實例結果截圖:異步

files集合只能知道一些文件的基本信息,FileReader類型纔是File API的重頭戲post

FileReader類型

FileReader類型實現是一種異步文件讀取機制,讀取的是文件系統。能夠經過如下方法讀取文件中的內容ui

方法名 參數 輸出內容 描述
readAsText file,encoding 純文本 異步以純文本形式讀取文件,將讀取到的文本保存在result屬性中
readAsDataURL file DataURI的形式 異步讀取文件並將文本以數據URI的形式保存在result屬性中
readAsBinaryString file 二進制 異步讀取文件內容並將包含文件內容的二進制字符串保存在result屬性中
readAsArrayBuffer file ArrayBuffer 異步讀取文件並將一個包含文件內容的ArrayBuffer保存在result屬性中
abort -- -- 用於中斷文件讀取過程

具體文件輸出代碼:url

<input type='file' id='files'>
<script>
    var files = document.getElementById('files')
    files.addEventListener('change', function (event) {
        let file = event.target.files[0]
        let reader = new FileReader()
        reader.readAsDataURL(file)
        reader.onload = function () {
            console.log(reader.result)
        }
    })
</script>
複製代碼

咱們以上傳圖片,輸出DataURL爲例spa

其餘三種不一樣的文件輸出,只需將上述reader.readAsDataURL(file)的代碼替換方法便可,因爲篇幅有限,就不在此展開,讀者能夠建立對應的文件一一嘗試

由於文件讀取過程是異步的,FileReader也提供了幾個對應的事件,同時在上述的代碼中,咱們也已經使用了FileReader中的load事件來判斷是否已經讀完整個文件

事件名稱 事件描述
onabort 讀取被終止時調用
onerror 讀取出錯時調用
onload 讀取成功時調用
onloadend 讀取完成時調用,無論是讀取成功仍是失敗
onloadstart 讀取將要開始時出發
onprogress 讀取過程當中週期性觸發,每50ms左右觸發一次,能夠用來監聽文件讀取的進度

讀取部份內容

有時候,咱們只想讀取文件的一部分而不是所有內容。爲此,File對象還支持了一個slice()方法,slice()方法接受兩個參數:起始字節數以及要讀取的字節數。這個方法返回一個Blob實例,Blob是File類型的父類型

咱們新建一個從1到10的txt,讀取1-5的內容

輸出結果:

如下就是讀取文件部份內容的代碼

<input type='file' id='files'>
<script>
    var files = document.getElementById('files')
    files.addEventListener('change', function (event) {
        let file = event.target.files[0]
        let reader = new FileReader()
        blob = file.slice(0, 10)
        reader.readAsText(blob)
        reader.onload = function () {
            console.log(reader.result)
        }
    })
</script>
複製代碼

對象URL

有時候咱們想要上傳圖片以後,直接在網頁中展現出來,這時候,咱們就可使用對象URL

對象URL也被稱爲blob URL,指的是引用保存在FileBlob中數據的URL,要建立對象URL,可使用window.URL.createObjcetURL()方法,並傳入FileBlob對象,方法就會返回一個字符串,指向一塊內存地址。那麼咱們就能夠動態將字符串URL插入img標籤中,從而實現網頁上傳圖片展現了

具體代碼以下:

<input type='file' id='files'>
<div id='images'></div>
<script>
    var files = document.getElementById('files')
    var images = document.getElementById('images')
    files.addEventListener('change', function (event) {
        let file = event.target.files[0]
        url = window.URL.createObjectURL(file)
        if (url) {
            images.innerHTML = `<img width='300' height='300' src=${url} />`
        }
    })
</script>
複製代碼

若是已經不須要了相對應的對象URL數據,最好釋放它佔用的內容。咱們能夠經過將對象URL傳給window.URL.revokeObjectURL(),那麼就能手工釋放其佔用的內存

讀取拖拽文件

咱們能夠結合HTML5拖拽API文件API,來實現從桌面把文件拖放到對應網頁的目標上。從桌面上把文件拖放到瀏覽器中會觸發drop事件,從而就能經過event.dataTransfer.files讀取到拖拽文件的信息

當文件拖拽網頁位置上以後能獲取到文件的信息:

具體代碼以下:

<div id='droptarget' style="width: 200px; height: 200px; border:1px solid black"></div>
<script>
    var droptarget = document.getElementById('droptarget')
    droptarget.addEventListener('drop', function (event) {
        event.preventDefault(); //禁止瀏覽器默認行爲,瀏覽器默認會直接打開顯示
        if (event.type === 'drop') {
            //獲取文件信息,同File對象相同
            var files = event.dataTransfer.files;
            console.log(
                `文件名稱:${files[0].name},文件類型:${files[0].type},文件大小:${files[0].size} bytes`
            )
        }
    })
    droptarget.addEventListener('dragenter', function (event) {
        //禁止瀏覽器默認行爲,瀏覽器默認會直接打開顯示
        event.preventDefault();
    })
    droptarget.addEventListener('dragover', function (event) {
        //禁止瀏覽器默認行爲,瀏覽器默認會直接打開顯示
        event.preventDefault();
    })
</script>
複製代碼

使用XHR文件上傳

咱們已經能夠經過File API來訪問到文件中的內容,那麼咱們就能夠利用這一點來經過XHR實現文件的上傳。咱們能夠經過FormData以表單的方式來上傳文件內容。首先咱們建立一個FormData對象,經過調用append()方法並傳入相應的File對象做爲參數,再經過XHRsend()方法,就能夠將文件內容上傳到服務器端。

具體的代碼根據上面的讀取拖拽文件代碼進行改造,從而實現拖拽文件上傳:

droptarget.addEventListener('drop', function (event) {
    event.preventDefault();
    if (event.type === 'drop') {
        var data = new FormData();
        var files = event.dataTransfer.files;
        data.append("file", files[0]) //若是有多個文件上傳,可對應遍歷files對象加入到data中
        var xhr = new XMLHttpRequest();
        xhr.open('post', url, true); //url表示文件上傳服務器的地址
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4) {
                console.log(xhr.responseText)
            }
        }
    }
    xhr.send(data);
})
複製代碼

最後

若是以爲文章對你有幫助,請幫忙多多點贊,動動小手,你的點贊是我寫做最大的動力

相關文章
相關標籤/搜索