如何優雅的處理前端開發中的File

本文首發於公衆號:符合預期的CoyPan

寫在前面

在前端開發中,咱們常常會遇到對文件的操做,特別是對圖片的操做。在Node端,提供了file相關的接口,供咱們使用。在瀏覽器中,Html5提供了File相關的Web Api。javascript

本文將小小總結一下如何使用File相關的api來操做文件以及相關的一些知識。html

File對象

一個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對象

那麼,如何獲取一個文件對象呢?上面提到了,咱們能夠直接使用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>

如何讀取File對象的內容

上面講了如何拿到一個文件對象,那麼怎麼讀取文件的內容呢?這個時候,就須要用到另一個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),才能展現出來。

如何從頁面上下載一個自定義的File

下面的場景是比較常見的:在頁面上生成一個自定義文件,而後下載下來。要實現這個需求,能夠按照下面的思路:

  1. 首先生成一個文件。這個在前文有講到,咱們能夠直接使用 new File 來構造一個文件便可。
  2. 生成一個對該文件的引用。可使用 window.URL.createObjectURL 來建立對文件的引用。
  3. 下載。使用 a 標籤,設置download屬性。

代碼示例:

<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已經支持直接讀寫本地文件了。點我

相關文章
相關標籤/搜索