HTML input type=file檔案選擇表單元素二三事

發表於2015-11-24

一、良生- input type=file與檔案上傳

本文所說的input type=file指的是type型別是fileinput元素,最簡HTML程式碼如下:

但是,為了習慣,我們多寫成:

在HTML5出現之前(XHTML),我們的閉合規則則有些出入:

顧名思義,選擇檔案,並上傳檔案。

在萬惡的舊時代,HTML5還沒有出現之前,原生的file input表單元素只能讓我們一次上傳一張圖片。無法滿足一次上傳多圖的互動需求,所以,很多場景,就被swfupload.js給取代了,有點逐漸淡出人們視野的感覺。

然,技術發展,日新月異,三十年河東,三十年河西。隨著原生HTML5表單對多圖(multiple屬性)、上傳前預覽,二進位制上傳等支援越來越廣泛,原生的file input表單元素又迎來了新的升級,flash為背景的swfupload.js註定要落寞。

但是,對於PC專案,IE8-IE9瀏覽器還是不能忽略的。所以,現在,很流行的一種處理方式,就是HTML5 file上傳和flash swfupload上傳一起整合的模式,優先使用原生HTML5上傳,不支援的,使用flash上傳。我之前有篇關於HTML5上傳的文章,每天訪問量很高的:“基於HTML5的可預覽多圖片Ajax上傳”,大家有興趣可以看看。

二、蓮安-原生input上傳與表單form元素

如果想使用瀏覽器原生特性實現檔案上傳(如圖片)效果,父級的form元素有個東西不能丟,就是:

enctype屬性規定在傳送到伺服器之前應該如何對錶單資料進行編碼,預設的編碼是:”application/x-www-form-urlencoded“。對於普通資料是挺適用的,但是,對於檔案,科科,就不能亂編碼了,該什麼就是什麼,只能使用multipart/form-data作為enctype屬性值。

無論是舊時代的單圖上傳,還是HTML5中的多圖上傳,均是如此。

三、沿見-原生file input圖片上傳前預覽與Ajax上傳

檔案,尤其圖片,上場前能夠預覽,是很棒的互動體驗。不走伺服器,不耗費流量,多棒!

理想雖好,實現起來……

在HTML5還沒出現的舊時代,只有低版本的IE瀏覽器貌似有方法,使用私有的濾鏡,超越安全的限制(其實是利用了不好的東西),實現圖片直接預覽;但是呢,那個時候,Chrome, FireFox沒有這一出,於是,想要使用原生file input實現圖片的上傳前預覽,相容性坎很難跨過去。

但是,後來,HTML5來了,我們出現了轉機,IE10+以及其他現代瀏覽器,可以讓我們直接讀取圖片的資料,然後在頁面上呈現,實現了上傳前預覽;加上之前老IE的濾鏡策略,貌似,可行。但是呢但是,老的IE瀏覽器只能最多一次選擇一個檔案,因此,只有單圖上傳的時候,大家可以考慮考慮。

傳統的form提交,是要改變頁面流的,也就是重新整理後跳轉。好的體驗應該是走Ajax互動的。HTML5裡面支援二進位制formData資料提交,因此,可以從容Ajax提交上傳的檔案資料;那老舊的IE瀏覽器怎麼辦?

一般方法如下:

  1. form元素新增target屬性,其值指向頁面內隱藏的一個<iframe>元素的id, 如下示意:
  2. 處理<iframe>元素的onload事件,獲得返回內容(如下程式碼示意),具體細節非本文重點,不表。

OK, 當然,你也可以不用像上面這麼麻煩,直接使用jquery.form.js. 原理呢,就是上面這樣,但是,不需要這麼麻煩。

四、恩和-原生file input大小、按鈕文字等UI自定義

原生的file input不收待見的另外一個原因是:長的醜還不好控制。

舉個例子,下圖這個“選擇檔案”這幾個文字,我們就不好對file控制元件動刀子實現自定義:
file input框

怎麼辦呢?

有一種方法是這樣的:
讓file型別的元素透明度0,覆蓋在我們好看的按鈕上。然後我們去點選好看的按鈕,實際上點選是是file元素。

然而,此方法有一些不足:

  1. 尺寸控制不靈活。CSS width屬性有些瀏覽器不管用,需要使用size,然後高度控制也不精準,我們很難正好覆蓋在好看的自定義按鈕上。
  2. 樣式不好控制,按鈕的hover態以及active態不好處理。
  3. HTML結構限制以及定位成本。

更好的方法是,使用label元素與file控制元件關聯,好處在於:

  1. 點選自定義的漂亮按鈕就是點選我們file控制元件;
  2. 沒有尺寸控制不精確的問題;
  3. 沒有不能響應hover態active態的問題;
  4. 我們的漂亮按鈕甚至可以在form表單元素的外面,例如:

    效果如下(真實實時效果):

五、盈年-file型別控制元件的accept屬性

input file型別控制元件有一個屬性,名為accept, 可能有些小夥伴不太瞭解。可以用來指定瀏覽器接受的檔案型別,也就是的那個我們開啟系統的選擇檔案彈框的時候,預設介面中呈現的檔案型別。例如:accept="image/jpeg",則介面中只有jpg圖片,如下截圖,同時,窗體右下方是“自定義檔案”按鈕:
自定義檔案

實際開發的時候,很少只允許傳jpg圖片,應該都是隻能傳圖片型別,此時,可以使用:

於是乎,“自定義檔案”按鈕變成了語義更明確的“圖片檔案”:
圖片檔案

accept屬性值其實是MIME型別, 例如下面幾個可能常用的:

然後,多個屬性值使用逗號分隔,例如:

六、又及-input file值的清除

現代瀏覽器直接value = "", 有些IE瀏覽器貌似不行,好像使用file.outerHTML = file.outerHTML,我自己沒測試。

不過我覺得比較麻煩,還要判斷瀏覽器什麼的。像本文的Ajax單圖上傳,直接form.reset()就可以了。

以上~

相關文章