Upload file with File API

ECMAScript:6

如果想要在前端直接上傳檔案,可以透過 Javascript 的 File API 處理。

File API 中包含了幾個比較重要的 interface:

  • File:可以用來讀取硬碟上檔案相關檔案資訊的物件
  • FileList:File 物件的集合
  • Blob:表示檔案內容的物件
  • FileReader:讀取檔案用的物件

Input File

如果網頁取得或寫入資料是透過 API 方式的話,那就必須透過 Javasciprt 整理好參數再送出,上傳檔案的部份也不例外。

以下實作一個讀取 <input> tag 中的圖片範例:

html

<!-- 當設定 multiple,就可以上傳多個檔案 -->
<input id="example" type="file" multiple>
<div id="img-list"></div>
document.querySelector('#example').addEventListener('change', function (event) {
  // 取得檔案清單
  let filelist = event.target.files;

  for (let i = 0; i < filelist.length ; i++ ) {
    // 判斷是否為圖片
    if (!filelist[i].type.match('image.*')) {
      continue;
    }

    // 透過 FileReader 取得檔案內容
    let reader = new FileReader();

    // 設定檔案讀取完畢時觸發的事件
    reader.onload = event => {
      // event.target.result 為圖片編碼
      // 將圖片即時呈現在瀏覽器上
      let e = document.createElement('div');
      let html = <img src="${event.target.result}">;
      e.innerHTML = html;

      document.querySelector('#img-list').appendChild(e);
    };

    // 利用 DataURL 的格式讀取圖片
    reader.readAsDataURL(filelist[i]);
  }
});

Drag、Drop File

純前端上傳檔案最常見的就是使用 拖拉 的方式直接上傳,這種方式就最適合使用 File API 來做。

以下實作一個讀取拖拉檔案的範例:

css

#drop-zone {
  width: 100%;
  border: 2px dashed #BBB;
  border-radius: 5px;
  padding: 25px;
  text-align: center;
  color: #BBB;
}

html

<div id="drop-zone">Drop file here</div>

javascript

// 需要定義 dragover 事件,並設定 preventDefault()
// 如果沒有定義,會在觸發 Drop 事件之前就把檔案開啟了
document.querySelector('#drop-zone').addEventListener('dragover', function (event) {
  // 取消拖拉時開啟檔案
  event.preventDefault();
});

document.querySelector('#drop-zone').addEventListener('drop', function (event) {
  // 取消拖拉時開啟檔案
  event.preventDefault();

  // 取得拖拉的檔案清單
  let filelist = event.dataTransfer.files;
  for (let i = 0; i < filelist.length; i++) {
    // 檔案名稱
    console.log(filelist[i].name);

    // 檔案類型
    console.log(filelist[i].type);

    // 檔案大小
    console.log(filelist[i].size);

    // 透過 FileReader 取得檔案內容
    let reader = new FileReader();

    // 設定檔案讀取完畢時觸發的事件
    reader.onload = event => {
      // 取得檔案完整內容
      console.log(event.target.result);

      // 上傳檔案到伺服器端
      // upload(file);
    };

    // 設定 onprogress event 查詢進度
    reader.onprogress = function (evt) {
      // 確定 evt 是否為 ProgressEvent
      if (evt.lengthComputable) {
        // 計算百分比
        let percentLoaded = Math.round((evt.loaded / evt.total) * 100);

        // 注意:這裡的百分比的數字不會到 100
        console.log(percentLoaded);
      }
    };

    // 開始讀取檔案,以文字字串型式讀取資料
    reader.readAsText(filelist[i]);
  }
});
Categories: JavaScript