js資料夾上傳
資料夾上傳:從前端到後端
檔案上傳是 Web 開發肯定會碰到的問題,而資料夾上傳則更加難纏。網上關於資料夾上傳的資料多集中在前端,缺少對於後端的關注,然後講某個後端框架檔案上傳的文章又不會涉及資料夾。今天研究了一下這個問題,在此記錄。
先說兩個問題:
- 是否所有後端框架都支援資料夾上傳?
- 是否所有瀏覽器都支援資料夾上傳?
第一個問題:YES,第二個問題:NO
只要後端框架對於表單的支援是完整的,那麼必然支援資料夾上傳。至於瀏覽器,截至目前,只有 Chrome 支援。 Chrome 大法好!
不要期望檔案上傳這個功能的瀏覽器相容性,這是做不到的。
好,假定我們的所有使用者都用上了 Chrome,要怎麼做才能成功上傳一個資料夾呢?這裡不用drop
<input>
。用表單 submit 和 ajax 都可以做,先看 submit 方式。<form method="POST" enctype=multipart/form-data>
<input type='file' name="file" webkitdirectory >
<button>upload</button>
</form>
我們只要新增上 webkitdirectory
這個屬性,在選擇的時候就可以選擇一個檔案夾了,如果不加,資料夾被選中的時候就是灰色的。不過貌似加上這個屬性就沒法選中檔案了... enctype=multipart/form-data
如果用 ajax 方式,我們可以省去<form>
,只留下<input>
就 OK。
<input type='file' webkitdirectory >
<button id="upload-btn" type="button">upload</button>
但是這樣是不夠的,關鍵在於 Js 的使用。
var files = [];
$(document).ready(function(){
$("input").change(function(){
files = this.files;
});
});
$("#upload-btn" ).click(function(){
var fd = new FormData();
for (var i = 0; i < files.length; i++) {
fd.append("file", files[i]);
}
$.ajax({
url: "/upload/",
method: "POST",
data: fd,
contentType: false,
processData: false,
cache: false,
success: function(data){
console.log(data);
}
});
});
用 ajax 方式,我們必須手動構造一個 FormData
Object, 然後放在 data 裡面提交到後端。 FormData
好像就只有一個 append
方法,第一個引數是 key,第二個引數是 value,用來構造表單資料。ajax
請求中,通過 input 元素的 files 屬性獲取上傳的檔案。files
屬性不論加不加 webkitdirectory
都是存在的,用法也基本一樣。不過當我們上傳資料夾時,files
中會包含檔案相對路徑的資訊,之後會看到。
用 ajax 上傳的好處有兩點,首先是非同步,這樣不會導致頁面卡住,其次是能比較方便地實現上傳進度條。關於上傳進度條的實現可以參考這裡。需要注意的是contentType
和processData
必須設定成false
,參考了這裡。