在上傳檔案時,最討厭的莫過於檔案上傳了 5 分鐘後才跟我說檔案過大或尺寸不正確! 在檔案上傳的驗證我們往往交給後端處理,導致檔案需要上傳後才能確認是否符合規定,特別是圖檔還有長寬比例的問題需要檢查,這些事情如果完全交給後端,就可能導致用戶體驗不佳,之前在新頭殼研究大頭貼上傳時,發現原來完全可以將這些事情交給前端處理,透過 JS 和 HTML5 API 做到檔案上傳的格式、大小(20MB)、尺寸(100×100) 檢查,甚至還可以做到預覽、前端切圖轉檔等等!
在開始前,請務必閱讀這些重要的注意事項
- 上傳檔案驗證這事情,絕對不能只教給前端處理;後端依舊要檢查,只是前端處理可以讓使用者體驗更好。
- 請務必考慮到少數瀏覽器、手機可能不支援前端檢查的可能性。
- 不建議完全交由前端剪裁圖片、轉換格式,雖然可以降低伺服器 Loading 並加快傳輸速度,但瀏覽器相容性需要考慮到,建議是「如果瀏覽器支援,就在前端剪裁,否則後端處理」這樣的合作方式。
在 HTML 有提供 File、FileReader、Image 這三組 API,透過他們可以達到檔案上傳的格式、尺寸、大小檢查以及預覽功能;這三組 API 的瀏覽器支援度都還算不錯,不過在智慧型手機上略有些差異,可點擊上方超連結查詢。
檔案大小、格式檢查
當你在 form:input 上傳檔案後,可以從 input:file 的 DOM 上獲得 File 物件,並檢查檔案大小(Byte) 和格式,可參考下方範例:
HTML
<input type="file" id="uploader">
JavaScript
$("#uploader").change(function(){ var upploader_dom = $("#uploader")[0]; # 假設單檔上傳,所以直接取第零個檔案 console.log(uploader_dom.file[0].size + " KB"); # 檔案格式是以副檔名來做判斷 console.log(uploader_dom.file[0].type); })
檔案預覽
如果你想做非圖檔預覽或檔案尺寸檢查,建議先閱讀這邊。
在檔案上傳後(change edvent)透過 FileReader 物件將使用者上傳的檔案以 DataURL 格式讀取後設為 img 的 src 屬性,如果一來就可以再不經由後端伺服器、不上傳檔案的情況下預覽圖檔內容。
HTML
<img id="preview_img" alt="empty preview"> <input type="file" id="uploader">
JavaScript
var reader = new FileReader(); reader.onload = function(e) { $("#preview_img").attr("src", e.target.result); } $("#uploader").change(function() { var upload_file = $("#uploader")[0].files[0]; reader.readAsDataURL(upload_file); })
除了 FileReader.readAsDataURL() 外,其實也有readAsText()、readAsBinaryString() 等方法可使用,因此也可以做到非圖檔預覽,例如讀取文字檔後顯示在 Textarea。
圖檔尺寸檢查
在上傳大頭貼或橫幅等圖檔時,會需要針對圖檔的長寬比例進行檢查。 其實在 <img> 這個 HTML Tag 可以取得圖檔案寬度、高度,例如:
<img src="https://example.com/hi.jpg"> <script> var img_dom = $("img")[0]; console.log(img_dom.width); console.log(img_dom.height); </script>
在 img dom 裡面的傢伙就是 Image 物件,如果有興趣知道更多用法、屬性可以到 MDN Image API 查閱。
透過上面介紹到的特性,和 FileReader、File 結合,就可以檢查上傳圖檔的長寬比例,請參考範例程式碼:
HTML
<input type="file" id="uploader">
JavaScript
var reader = new FileReader(); var img = new Image(); reader.onload = function(e) { img.src = e.target.result; } img.onload = function() { console.log(this.width); console.log(this.height); } $("#uploader").change(function() { var upload_file = $("#uploader")[0].files[0]; reader.readAsDataURL(upload_file); })
謝謝分享,非常實用!
$(“#uploader”).change(funnction(){…}
這裡 function 多了一個 n
謝謝提醒,已修改!!