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]);
}
});