本篇要解決的問題
最近朋友遇到一個需求,就是要客製上傳檔案的按鈕。找了一下以前寫過的東西,那時的寫還不是說很懂,是用 JS 在 trigger click,而不是直接用 label for
的特性。想了一下,覺得寫成一篇,然後把 code 更新一次再存起來,以後要用比較好找。
客製上傳檔案 input HTML 部份
HTML 的部份,因為 input type="file"
會被隱藏起來,按鈕樣式實際是寫在 label
上,就要用 input id
、label for
的這個特性,讓 label
被點擊時可以去 trigger input 被點擊。
另外案例的部份加上限制選擇的檔案只能是圖片檔,整理後如下:
<input id="customFileInput" type="file" accept="image/*"> <label for="customFileInput" class="button-primary">客製選擇檔案按鈕</label>
可以看到 input
的 id
,跟 label
的 for
,兩個值要是相同的,這樣就可以把 label
跟 input
綁起來。
實際上,很多那種寫不用 JS 就可以 trigger 一些功能的 Demo 都是這樣寫的。像是不用 JS 寫開啟 Modal,或是客製 radio
、checkbox
,都是隱藏 input
,樣式刻在 label
上,再用 id
、for
去綁,這樣當 label
被點擊時,input
也會被 click,就可以寫 input:checked + label
的樣式。
這部份例子可以看這個:客製 checkbox、radio、pure css modal box
在限制選擇檔案的部份,HTML 就用 accept="xxxx"
就行。type
的值參考 w3schools:
- audio/*
- video/*
- image/*
- 只接指定副檔名,如:*.gif, *.jpg, *.png, *.doc
想要多個值就用半形逗號分開就行:
<input accept="audio/*,video/*,image/*">
客製上傳檔案 input JS 部份
JS 是用 File API,使用起來比想像中簡單,變數抓 input
,當 input
change 時,抓 event.target.files
就可以了。
本篇示範的是一次只傳一個檔案,多個檔案以後有時間再來寫。
JS 範例 code 如下:
var inputFile = document.getElementById('customFileInput'); inputFile.addEventListener('change', function(event) { var fileData = event.target.files[0]; // 檔案資訊 });
console.log(fileData)
的話,可以看到以下資訊:
- lastModifiedDate:檔案最後修改的時間
- name:檔案名稱
- size:檔案大小
- type:檔案類型
另外還有 2 個:lastModified、webkitRelativePath,一個是修改時間的毫秒數,一個非標準值,就不用了。
以下 JS 是抓值的部份:
var fileData = e.target.files[0]; // 檔案資訊 var fileName = fileData.name; // 檔案名稱 var fileType = fileData.type; // 檔案類型 var fileSize = Math.floor(fileData.size * 0.001); // 檔案大小轉成kb var fileTime = fileData.lastModifiedDate;
要補充的是,如果檔案是圖片檔,是可以產生縮圖的,這要用另一個 API:
URL.createObjectURL()
URL.createObjectURL(fileData)
就會產生一個 blob 的路徑,放進 img
的 src
裡就行。
示範頁面
製作了一個示範頁面,選完檔案後可以看到被選檔案的資訊:
https://letswritetw.github.io/letswrite-file-api-custom-input/
原始碼的部份也放上 Github 了:
https://github.com/letswritetw/letswrite-file-api-custom-input


[…] File API 客製上傳檔案按鈕 / input file […]
[…] File API 客製上傳檔案按鈕 / input file […]