本篇文章的主要目的是介紹本地文件相關(guān) API
的使用,好的蚕礼,廢話不多說(shuō)梢什,下面直接開(kāi)始。
基礎(chǔ)的 File API
File Api
提供了在瀏覽器中與本地文件進(jìn)行交互的最基礎(chǔ)的方法囤躁,不過(guò)值得注意的是荔睹,由于安全問(wèn)題,開(kāi)發(fā)者并不能主動(dòng)的去訪問(wèn)客戶端的文件信息严沥,也就是說(shuō)這一過(guò)程需要用戶的參與中姜,最常用的獲取本地文件的手段莫過(guò)于兩種:
- 用戶通過(guò)
input[type = file]
控件選擇了本地某個(gè)文件丢胚。 - 用于通過(guò)拖拽將本地的某一文件拖到瀏覽器完成上傳。
通過(guò)上面兩種形式携龟,我們都可以獲取到可以操作的 File
接口峡蟋,不過(guò)還有一點(diǎn)值得注意的是华望,無(wú)論是通過(guò)利用控件的形式還是通過(guò)拖拽的形式仅乓,用戶都可以同時(shí)選中多個(gè)文件,而當(dāng)用戶選擇多個(gè)文件的時(shí)候我們獲取到的其實(shí)是 FileList
接口宾抓,顧名思義豫喧,它就是一個(gè) File
接口的集合。
那么讲衫,通過(guò) File
接口我們能夠獲取到哪些信息呢鸟妙?
-
name
: 文件名 -
type
:ASCII
編碼,MIME
格式的文件類型。 -
size
: 文件所占的字節(jié) (byte
)忽匈。 -
lastModifiedDate
: 文件最后修改的日期和時(shí)間丹允。
注: File API
不能遍歷文件目錄。
通過(guò)上面介紹的這些內(nèi)容折柠,我們就可以很輕易的寫(xiě)出一個(gè)小 demo
批狐,就像下面的這樣。
其實(shí)現(xiàn)過(guò)程就是利用 input[type=file]
控件選擇多個(gè)文件承冰,不過(guò)在這里我們并沒(méi)有直接使用這個(gè)控件食零,而是利用 button
來(lái)觸發(fā)這個(gè)控件的功能。然后通過(guò)用戶選擇的文件會(huì)返回一個(gè) FileList
對(duì)象娜搂,通過(guò)對(duì)其包含的每個(gè) File
進(jìn)行屬性的讀取即可。其核心代碼如下:
uploadButton.addEventListener("click", function() {
fileInput.click();
}, false);
fileInput.addEventListener("change", function() {
if (fileInput.files) {
var length = fileInput.files.length;
for(var i = 0; i < length; i++) {
fileList.appendChild(getFileDetailDIV(fileInput.files[i]));
}
}
}, false);
這個(gè)時(shí)候這個(gè)小 demo
還不夠人性化考廉,畢竟有的人他就是不喜歡利用控件上傳文件恳谎,他就是喜歡利用拖放將文件傳上來(lái)因痛,那么為了這部分用戶,我們就得多費(fèi)點(diǎn)腦筋了鸵膏,怎么才能利用拖放獲取到一個(gè)文件的信息呢谭企?
在這之前,我想插入一些拖放的知識(shí)非区。因?yàn)榫W(wǎng)頁(yè)中并不是每一種元素都可以成為放置目標(biāo)盹廷,所以如果想自定義放置目標(biāo),那么我們需要修改 dragover
和 dragenter
的默認(rèn)行為管怠,代碼如下:
var droptarget = document.getElementById("custom-target");
droptarget.addEventListener("dragenter", function(e) {
e.preventDefault();
}, false);
droptarget.addEventListener("dragover", function(e) {
e.preventDefault();
}, false);
還有一點(diǎn)值得注意的是缸榄,當(dāng)你將目標(biāo)拖拽到地點(diǎn)以后,鼠標(biāo)松開(kāi)的時(shí)候就會(huì)觸發(fā) drop
事件她肯,不過(guò)放置事件也是有默認(rèn)行為的欲低,比如當(dāng)拖拽的目標(biāo)是圖片的時(shí)候,頁(yè)面就會(huì)轉(zhuǎn)向圖片瑞筐,當(dāng)拖拽的目標(biāo)是音樂(lè)或者視屏的時(shí)候,頁(yè)面就會(huì)按照默認(rèn)的方式打開(kāi)這些文件块蚌,所以如果不想這些事情發(fā)生膘格,我們需要阻止 drop
事件的默認(rèn)行為。
最后一點(diǎn)纱控,當(dāng)我們拖拽文件的時(shí)候菜秦,通過(guò) dataTransfer,files
就可以獲得選中的文件,而且其返回的結(jié)果是 FileList
接口尔店。下面就讓我們以拖拽的形式完成上面的功能主慰。
其核心代碼如下所示:
dragtarget.addEventListener("dragenter", function(e) {
e.preventDefault();
}, false);
dragtarget.addEventListener("dragover", function(e) {
e.preventDefault();
}, false);
dragtarget.addEventListener("drop", function(e) {
e.preventDefault();
var files = e.dataTransfer.files,
length = files.length;
for(var i = 0; i < length; i++) {
fileList.appendChild(getFileDetailDIV(files[i]));
}
}, false);
File Reader
上面已經(jīng)介紹了 File API
的使用共螺,不過(guò)僅僅是能夠獲取到文件的屬性,實(shí)用價(jià)值非常有限沙庐,所以在 HTML5 File API
中提供了一個(gè)新的接口 FileReader
佳吞,該接口為開(kāi)發(fā)者提供了從客戶端 JS
異步讀取文件的方法底扳,屬性和事件贡耽,下面就先來(lái)看看它提供的四種不同的讀取方法。
-
readAsArrayBuffer( Blob )
: 以ArrayBuffer
格式返回文件內(nèi)容阱冶。 -
readAsBinaryString( Blob )
: 以二進(jìn)制字符串的形式返回文件內(nèi)容滥嘴。 -
readAsText( Blob, [, encoding] )
: 以DOMString
文本返回文件內(nèi)容。 -
readAsDataURL( Blob )
: 以數(shù)據(jù)URL DOMString
返回文件內(nèi)容镊叁。
事件如下:
-
loadstart
: 文件讀取操作開(kāi)始時(shí)觸發(fā)。 -
progress
: 瀏覽器讀取文件過(guò)程中觸發(fā)疤苹。 -
abort
: 執(zhí)行放棄操作時(shí)觸發(fā)敛腌。 -
error
: 文件讀取過(guò)程中出現(xiàn)錯(cuò)誤時(shí)觸發(fā)。 -
load
: 文件成功讀取后觸發(fā)尤莺。 -
loadend
文件讀取完成后(無(wú)論成功或者失斝坠琛)觸發(fā)。
既然已經(jīng)知道了這么多的事件和方法捷绑,那么我們就的知道當(dāng)讀取完成后氢妈,我們需要的信息存放在何處?
通過(guò)上面的介紹壮吩,我們已經(jīng)知道當(dāng)文件讀取成功后加缘,會(huì)觸發(fā) load
事件拣宏,我們想要的事件就在 load
事件中的 event.target.result
中。下面我們針對(duì)各個(gè)方法做實(shí)驗(yàn)宋下,首先創(chuàng)建一個(gè)文本 test.txt
辑莫,其內(nèi)容如下:
You can import usage data from your Google Analytics account and see exactly how well a feature is supported among your own site's visitors. Look under the Settings panel to get started!
關(guān)于 readAsArrayBuffer()
和 readAsBinaryString()
這兩個(gè)方法在此就不演示了,因?yàn)槲覀€(gè)人對(duì) ArrayBuffer
的應(yīng)用場(chǎng)景還不是很清楚枝笨,所以下面直接利用 readAsText()
和 readAsDataURL()
這兩個(gè)方法。
利用 readAsText()
的代碼如下:
var fileReader = new FileReader();
fileReader.addEventListener("load", function(e) {
console.log(e.target.result);
}, false);
fileReader.readAsDataURL(file);
其返回的結(jié)果如下所示:
可見(jiàn)昭躺,它只是將你選擇的文本讀取出來(lái)了领炫,其實(shí)通過(guò)方法的名字你可能也已經(jīng)猜出大概了张咳。這有什么用呢?很明顯葱峡,我們可以利用這個(gè)方法編寫(xiě)一個(gè)在線閱讀或者修改的小應(yīng)用龙助。
還有一個(gè)方法是 readAsDataURL()
, 這個(gè)方法的返回值如下:
可見(jiàn)提鸟,這個(gè)方法只是返回一個(gè) URL
地址,而通過(guò)這個(gè)地址我們就可以獲取到選中的文件称勋,這個(gè)方法非常的有用赡鲜,比如你想開(kāi)發(fā)圖片預(yù)覽相關(guān)的功能或者是在線播放本地音頻的應(yīng)用,都可以利用該方法獲取到一個(gè)連接到本地資源的 URL
嘲更,然后進(jìn)行操作揩瞪。在以前,要完成同樣的功能,必須要將相應(yīng)的圖片或者資源上傳到服務(wù)器才可以使用纹因。
好了瞭恰,先寫(xiě)到這里,如果日后用到與文件操作相關(guān)的屬性,還會(huì)更新本文章密任!