HTML5 File API 全介紹

  在 HTML5 File API 出現以前,前端對於文件的操做是很是有侷限性的,大多須要配合後端實現。出於安全角度考慮,從本地上傳文件時,代碼不可能獲取文件在用戶本地的地址,因此純前端不可能完成一些相似圖片預覽的功能。可是 File API 的出現,讓這一切變成了可能。前端

一、FileList 對象canvas

  FileList 對象針對表單的 file 控件。當用戶經過 file 控件選取文件後,這個控件的 files 屬性值就是 FileList 對象。它在結構上相似於數組,包含用戶選取的多個文件。若是 file 控件沒有設置 multiple 屬性,那麼用戶只能選擇一個文件,FileList 對象也就只有一個元素了。後端

  好比我選擇了兩個文件,控制檯打印:數組

FileList {0: File, 1: File, length: 2} 0: File 1: File length:2 __proto__: Object

  通常來講,咱們不可能手動構造 FileList 對象,只能被動地讀取,也就是說只有用戶主動觸發了文件讀取行爲,js 才能訪問到 FileList,而這一般發生在表單選擇文件或者拖拽文件中。緩存

二、File對象安全

  一個 FileList 對象包含了咱們選中的 File 對象,那麼一個 File 又有哪些屬性呢?異步

  • name:文件名,該屬性只讀。
  • size:文件大小,單位爲字節,該屬性只讀。
  • type:文件的 MIME 類型,若是分辨不出類型,則爲空字符串,該屬性只讀。
  • lastModified:文件的上次修改時間,格式爲時間戳。
  • lastModifiedDate:文件的上次修改時間,格式爲 Date 對象實例。

  咱們能夠選一個文件,本身打印出來看看。函數

三、Blobthis

  File 對象是繼承自 Blob 對象的,Blob 又是什麼鬼?編碼

  Blob(Binary Large Object)對象表明了一段二進制數據,提供了一系列操做接口。其餘操做二進制數據的 API(好比 File 對象),都是創建在 Blob 對象基礎上的,繼承了它的屬性和方法。

  生成 Blob 對象有兩種方法:一種是使用 Blob 構造函數,另外一種是對現有的 Blob 對象使用 slice 方法切出一部分。

(1)Blob 構造函數,接受兩個參數。第一個參數是一個包含實際數據的數組,第二個參數是數據的類型,這兩個參數都不是必需的。

(2)Blob 對象的 slice 方法,將二進制數據按照字節分塊,返回一個新的 Blob 對象。

var a = ["hello", "world"]; var myBlob = new Blob(a, { "type" : "text/xml" }); var newBlob = myBlob.slice(0, 5); console.log(newBlob);

  Blob 對象有兩個只讀屬性:

  • size:二進制數據的大小,單位爲字節。(文件上傳時能夠在前端判斷文件大小是否合適)
  • type:二進制數據的 MIME 類型,所有爲小寫,若是類型未知,則該值爲空字符串。(文件上傳時能夠在前端判斷文件類型是否合適)

四、FileReader

  FileReader API 纔是咱們接下去完成一些任務的關鍵。FileReader API 用於讀取文件,即把文件內容讀入內存。它的參數是 File 對象或 Blob 對象

  對於不一樣類型的文件,FileReader 提供不一樣的方法讀取文件。

  • readAsText(Blob|File, opt_encoding):返回文本字符串。默認狀況下,文本編碼格式是 UTF-8,能夠經過可選的格式參數,指定其餘編碼格式的文本。
  • readAsDataURL(Blob|File):返回一個基於 Base64 編碼的 data-uri 對象。
  • readAsArrayBuffer(Blob|File):返回一個 ArrayBuffer 對象。

  除了以上三種不一樣的讀取文件方法,FileReader API 還有一個 abort 方法,用於停止文件上傳。

var reader = new FileReader(); reader.abort();

  FileReader 對象採用異步方式讀取文件,能夠爲一系列事件指定回調函數。

  • onabort 方法:讀取中斷或調用 reader.abort() 方法時觸發。
  • onerror 方法:讀取出錯時觸發。
  • onload 方法:讀取成功後觸發。
  • onloadend 方法:讀取完成後觸發,不論是否成功。觸發順序排在 onload 或 onerror 後面。
  • onloadstart 方法:讀取將要開始時觸發。
  • onprogress 方法:讀取過程當中週期性觸發。(能夠用來獲取文件讀取的進度)

  獲取到了文件的 base64 編碼,作一些諸如圖片預覽的功能,也就手到擒來了,有興趣的能夠本身嘗試下,相似的還有文字預覽啊,等等。

五、URL

  還有個強大的東西——URL 對象!

  調用 URL 對象的 createObjectURL 方法,傳入一個 File 對象或者 Blob 對象,能生成一個連接。

var objecturl =  window.URL.createObjectURL(blob);

  上面的代碼會對二進制數據生成一個 URL,這個 URL 能夠放置於任何一般能夠放置 URL 的地方,好比 img 標籤的 src 屬性。須要注意的是,即便是一樣的二進制數據,每調用一次 URL.createObjectURL 方法,就會獲得一個不同的 URL。這個 URL 的存在時間,等同於網頁的存在時間,一旦網頁刷新或卸載,這個 URL 就失效。(File 和 Blob 又未嘗不是這樣呢)除此以外,也能夠手動調用 URL.revokeObjectURL 方法,使 URL 失效。

  對於 File 或者 Blob 對象,咱們能夠這樣理解,它們的存在,依賴於頁面,而 URL 能給這些 "轉瞬即逝" 的二進制對象一個臨時的指向地址。這個臨時的地址還有什麼用呢?也能作圖片預覽,相比前面用 readAsDataURL 的實現,更簡單了。

<input type='file' multiple /><br/>
<img />
<script> document.querySelector("input").onchange = function() { var files = this.files; document.querySelector("img").src = window.URL.createObjectURL(files[0]); } </script>

六、Canvas & dataURL & Blob

  canvas 中有 toDataURL 函數,能夠將 canvas 轉爲 dataURL 形式的 base64 編碼,而 Blob 也能夠轉爲 dataURL,這三者之間是否能夠互相轉換?有沒有什麼實用之處?

(1)canvas -> dataURL

  用 toDataURL 方法,比較簡單,很少說。

(2)blob -> dataURL

  用 FileReader 的 readAsDataURL 方法

(3)dataURL -> blob

  這個函數有點屌

function dataURLtoBlob(dataurl) { var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--){ u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], {type:mime}); }

(4)dataURL - canvas

  將 image 的 src 屬性置爲 dataURL,再用 drawImage 方法畫上去。

(5)blob - canvas

  如何把二進制形式的圖片畫上 canvas?先用 readAsDataURL 轉爲 dataURL,接着就是 (4) 的事情了。

(6)canvas - blob

  canvas 有原生的 toBlob 方法,使得圖片文件能夠被緩存或保存到本地

  canvas 轉爲 blob 也能夠用 dataURL 作跳板,先將 canvas 轉爲 dataURL(1),再用 dataURL 轉爲 blob(3)。

  利用它們之間的轉換能夠作些什麼好玩的事呢?好比能夠上傳圖片,對圖片作各類處理,而後保存等。

相關文章
相關標籤/搜索