上傳檔案是一種很普通的Web應用,尤其以上傳圖片更為常見。今天我們就在Web標準的範圍內談談與這個主題相關的內容(只限前端部分,上傳的實現當然就不在此列了),關鍵詞是:Javascript、DOM和Firefox。
表單
先建立一個file表單域,我們需要用它來瀏覽本地檔案。
<form name="form1" id="form1" method="post" action="upload.php"><input type="file" name="file1" id="file1" /></form>
試下效果:
判斷檔案類型
當使用者選擇了一個圖片檔案時,我們希望他能馬上看到這張圖片的縮圖,以便他能確認沒有把自己的光屁股照片當作頭像傳到我們的伺服器上^_^。
在預覽之前我們還得先判斷一下使用者選擇的是不是一個影像檔,如果他想用一個.rar檔案做頭像的話我們也需要禮貌地提醒一下。
<form name="form2" id="form2" method="post" action="upload.php"><input type="file" name="file2" id="file2"onchange="preview()" /></form>
Javascript函數實現,注意我們使用DOM方法getElementById來訪問對象。不要再使用form和input的name屬性來訪問對象了,只有IE才這麼幹。
<script type="text/javascript">function preview2(){var x = document.getElementById("file2");if(!x || !x.value) return;if(x.value.indexOf(".jpg")<0&& x.value.indexOf(".jpeg")<0&& x.value.indexOf(".gif")<0){alert("您選擇的似乎不是影像檔。");}else{alert("通過");}}</script>
試下效果:
這裡有一個問題,如果使用者選擇了名為“fake.jpg.txt”的檔案,這段指令碼仍舊會認為這是一個合法的影像檔。一個可行的解決方案是先把檔案名稱轉換成小寫,再取檔案路徑的最後4到5位,判斷一下檔案的副檔名是否確為我們支援的影像檔副檔名。不過這種方案略顯笨拙,也沒有什麼美感可言,我們換一種方案:用“Regex”來判斷副檔名。
<script type="text/javascript">function preview3(){var x = document.getElementById("file3");if(!x || !x.value) return;var patn = //.jpg$|/.jpeg$|/.gif$/i;if(patn.test(x.value)){alert("通過");}else{alert("您選擇的似乎不是影像檔。");}}</script>
看看效果(可以自己建立一個“fake.jpg.txt”檔案試試):
如果從來沒有接觸過Regex,那這段指令碼對你可能會有些晦澀,不妨Google一把,看看是否可以先學習學習這方面的知識。我可以向你保證花四五個小時學點Regex會是你最近三個月內作出的最明智選擇^_^。
回到這段指令碼上來,即使你還看不懂Regex那兩行,但整段指令碼的美感還是很明顯的:簡潔、直接、語義流暢,這與Web標準關於XHTML的要求是一致的,與Web設計師或開發人員天生的“完美”主義也是一致的。
jjww一大段之後,我們轉入重點——
預覽圖片
預覽功能的基本設計思路是很清晰的:建立一個img元素,再把檔案域的value值賦值給img元素的src屬性。
<form name="form4" id="form4" method="post" action="#">
<input type="file" name="file4" id="file4"onchange="preview4()" />
<img id="pic4" src="" alt="圖片在此顯示" width="120"/></form>
<script type="text/javascript">
function preview4(){
var x = document.getElementById("file4");
var y = document.getElementById("pic4");
if(!x || !x.value || !y) return;
var patn = //.jpg$|/.jpeg$|/.gif$/i;
if(patn.test(x.value)){
y.src = "file://localhost/" + x.value;
}else{
alert("您選擇的似乎不是影像檔。");
}
}
</script>
試下效果:
如果你用的是Firefox(或Opera),可能會發現什麼也沒有發生。是的,很不幸Firefox的安全性原則不允許我們顯示一個使用者的本地影像檔。不知道他們為什麼要這麼做,我個人覺得影像檔並不會造成嚴重的安全性問題。即使是不久前比較熱門的那個會引起Windows崩潰的jpeg檔案,要顯示它的前提條件是使用者自己選擇了這個檔案或者你知道這個檔案在使用者硬碟上的準確路徑。所以我想這種策略很可能來自於一個“懶惰”的開發人員,他並不想多寫一些程式來區分這個本地檔案是一個影像檔還是一個惡意檔案,Firefox對安全性的要求讓他們有些過于敏感了。
讓Firefox顯示本地檔案的唯一辦法就是修改它的預設安全性原則:
- 在Firefox的地址欄中輸入“about:config”
- 繼續輸入“security.checkloaduri”
- 雙擊下面列出來的一行文字,把它的值由true改為false
然後你可以再試試上面預覽,everything works well!可惜的是我們並不能要求所有的使用者都去修改這個值(更不用說修改的過程還挺麻煩),所以這對我們來說毫無意義。我們能做的也許就是接受Firefox不能預覽本地圖片這種“可笑”的局面。
用DOM來建立對象
在上面的XHTML代碼中,我們為了預覽圖片,事先加入了一個沒有設定src的img對象。除去不美觀、代碼冗餘之外,如果使用者瀏覽器不支援Javascript,他不僅無法使用這個功能,還要接受頁面上一個永遠不會顯示出來的破圖。要解決這個問題,我們就需要在“運行時”再產生這個img對象,途徑還是DOM。
<form name="form5" id="form5" method="post" action="#">
<input type="file" name="file5" id="file5"onchange="preview5()"/>
</form>
<script type="text/javascript">
function preview5(){
var x = document.getElementById("file5");
if(!x || !x.value) return;
var patn = //.jpg$|/.jpeg$|/.gif$/i;
if(patn.test(x.value)){
var y = document.getElementById("img5");
if(y){
y.src = 'file://localhost/' + x.value;
}else{
var img=document.createElement('img');
img.setAttribute('src','file://localhost/'+x.value);
img.setAttribute('width','120');
img.setAttribute('height','90');
img.setAttribute('id','img5');
document.getElementById('form5').appendChild(img);
}
}else{
alert("您選擇的似乎不是影像檔。");
}
}
</script>
試下效果:
這樣就相對比較完美了。我也不解釋上面這些DOM方法的具體意義,Google一下什麼都有了。DOM和Regex一樣,都是“包你不悔”的實用技術,如果你希望更多瞭解、深入學習、或者順利實踐Web標準,DOM是不可或缺的。從我本人最近的體會來說,Javascript+DOM+CSS蘊藏著強大的能量,就看你怎麼釋放它了。