本文首發於公衆號:符合預期的CoyPan
在前端開發中,咱們常常會遇到對文件的操做,特別是對圖片的操做。在Node端,提供了file相關的接口,供咱們使用。在瀏覽器中,Html5提供了File相關的Web Api。javascript
本文將小小總結一下如何使用File相關的api來操做文件以及相關的一些知識。html
一個File對象包含了如下的屬性:前端
lastModified: 只讀。文件最後修改時間(UNIX時間戳)。 name: 只讀。文件名(不包含完整路徑)。 size: 只讀。文件大小。 type: 只讀。MIME TYPE。
看一個例子:java
在瀏覽器中,咱們也能夠直接使用File構造函數來構造一個文件對象實例。json
var json = `{ "a": 1 }`; var f = new File([json], 'test.json', { type: 'application/json' }); console.log(f);
一個File對象的內容能夠是不少數據類型,包括:ArrayBuffer、ArrayBufferView、Blob、DOMString(在JS中,DOMString就是String)。本文不作進一步詳細介紹。
那麼,如何獲取一個文件對象呢?上面提到了,咱們能夠直接使用File構造函數。大多數的狀況下,咱們是須要讓用戶進行選擇,這個時候,就須要用到 input 標籤了。代碼也很簡單,咱們只須要把input標籤的 type 設置爲 file 就行。api
<html> <input type='file'/> <script> const el = document.querySelector('input'); el.addEventListener('change', e=> { const fileList = e.target.files; [].slice.call(fileList).forEach(file => { console.log(file); }); }); </script> </html>
咱們只須要監聽input標籤的change事件,就能夠拿到文件對象了。這裏須要注意的時候,咱們拿到的實際上是一個文件列表,而這個文件列表是一個類數組對象,須要轉換爲數組,才能徹底像數組同樣遍歷。數組
若是想選擇多個文件,則須要在input標籤上增長 multiple 屬性。若是隻接受某些類型的文件,能夠添加 accept 屬性。瀏覽器
<!-- 能夠多選文件 --> <input type='file' multiple /> <!-- 多選,只能選擇圖片文件 --> <input type='file' multiple accept='image/*'/>
上面的圖中咱們能夠看到,直接使用input標籤是不太美觀的。咱們能夠將input標籤隱藏,使用代碼觸發input標籤的點擊事件,就能夠達到效果。app
<html> <input type='file' style="display:none"/> <button>這是一個帥氣的按鈕</button> <script> const inputEl = document.querySelector('input'); inputEl.addEventListener('change', e => { const fileList = e.target.files; [].slice.call(fileList).forEach(file => { console.log(file); }); }); const btnEl = document.querySelector('button'); btnEl.addEventListener('click', () => { inputEl.click(); }); </script> </html>
上面講了如何拿到一個文件對象,那麼怎麼讀取文件的內容呢?這個時候,就須要用到另一個Web Api了:FileReaderide
使用FileReader讀取文件內容,主要步驟爲:
// 一、聲明一個FileReader對象實例 var fileReader = new FileReader(); // 二、監聽讀取完成事件 fileReader.onload = function(e) { const result = e.target.result; } // 三、讀取文件內容 // 這裏的 file 爲文件對象。 fileReader.readAsDataURL(file); // 以base64的方式讀取 // fileReader.readAsArrayBuffer() 以ArrayBuffer的方式讀取 // fileReader.readAsText() 以字符串的方式讀取
一個很常見的場景:讀取本地圖片,並展現縮略圖。實現起來十分簡單。
<html> <input type='file' accept='image/*' /> <script> const el = document.querySelector('input'); el.addEventListener('change', e=> { const imgFile = e.target.files[0]; const reader = new FileReader(); reader.onload = function(e) { const base64 = e.target.result; const imgEl = new Image(); imgEl.src = base64; imgEl.onload = function() { document.body.appendChild(imgEl); } } reader.readAsDataURL(imgFile); }); </script> </html>
想要在瀏覽器中預覽文件,還有另一種方法:使用 window.URL.createObjectURL
window.URL.createObjectURL 能夠接受一個文件對象做爲參數,返回一個字符串。這個字符串是一個包含了一個對象URL,可用於指定源文件對象的內容。看下面的例子:
<html> <input type='file' accept='image/*' /> <script> const el = document.querySelector('input'); el.addEventListener('change', e=> { const imgFile = e.target.files[0]; const imgSrc = window.URL.createObjectURL(imgFile); console.log(imgSrc); const imgEl = new Image(); imgEl.src = imgSrc; imgEl.onload = function() { document.body.appendChild(imgEl); window.URL.revokeObjectURL(imgFile); } }); </script> </html>
能夠看到,這裏圖片的src,是一個以 blob:
開頭 的字符串。這是瀏覽器本身實現的一個協議,表示對一個資源的引用,須要掛載到網頁中的資源對象上(好比img,video),才能展現出來。
下面的場景是比較常見的:在頁面上生成一個自定義文件,而後下載下來。要實現這個需求,能夠按照下面的思路:
代碼示例:
<html> <button>點擊下載</button> <script> const btnEl = document.querySelector('button'); btnEl.addEventListener('click', function() { const json = `{ "a": 1 }`; const file = new File([json], 'test.json', { type: 'application/json' }); const url = window.URL.createObjectURL(file); const aTag = document.createElement('a'); aTag.href = url; aTag.download = 'test.json'; aTag.click(); }); </script> </html>
本文主要介紹了在前端頁面中,如何處理File。其實File對象是繼承自Blob對象,File是特殊的Blob。Blob 是 Binary Large Object 的縮寫,表示一個不可變、原始數據的類文件對象,主要用於處理二進制的數據。關於這一部分的內容,能夠移步這篇文章.
另外,最新版的Chrome已經支持直接讀寫本地文件了。點我