最近做了阿里雲的oss上傳,順便來總結下上傳文件的幾種主要方法。
第一種:經典的form和input上傳。
設置form的aciton為后端頁面,enctype="multipart/form-data",type=‘post’
<form action='uploadFile.php' enctype="multipart/form-data" type='post'> <input type='file'> <input type='hidden' name='userid'> <input type='hidden' name='signature'> <button>提交</button> </form>
使用input選擇文件,設置好其他input的值,點擊提交,將文件數據及簽名等認證信息發送到form設置的action對應的頁面,瀏覽器也會跳轉到該頁面。觸發form表單提交數據的方式有2種,一種是在頁面上點擊button按鈕或<input type='submit'>按鈕觸發,第二種是在js中執行form.submit()方法。
優點:使用簡單方便,兼容性好,基本所有瀏覽器都支持。
缺點:1. 提交數據后頁面會跳轉(下面會講如何禁止頁面跳轉)。
2.因為是瀏覽器發起的請求,不是一個ajax,所以前端無法知道什么時候上傳結束。
3. form表單里發送除文件外的數據,一般是新建一個type=hidden的input,value=‘需要傳的數據’,每發送一個數據就需要一個input,一旦多了就會使得dom看起來比較冗余。
小技巧:
form表單提交數據后會自動跳轉到action指定的頁面,為了禁止頁面跳轉,可以在頁面中新建一個空的ifame,比如name='upload',然后設置form的target="Uploader",form有一個target的屬性,規定在何處打開action,這樣form提交數據后就會仍停留在當前頁。代碼如下:
<form action='uploadFile.php' enctype="multipart/form-data" type='post' target="uploader1"> <input type='file'> <button>提交</button> </form> <ifrmae name='upload' id='uploader1'></iframe>
這樣寫的另一個好處是,可以知道什么時候上傳完成並接收到后端的回調結果。比如上面這個例子,文件數據發送到了 'uploadFile.php',假設該頁面處理完數據后返回了一個地址,該地址會被寫入到之前的iframe中。所以在ifame的onload函數觸發時,也就是上傳完成后,可以在iframe中讀取到后端返回的數據。
var iframe = document.getElementById('upload1'); iframe.onload = function () { var doc = window.frames['uploader1'].document; var pre = doc.getElementsByTagName('pre'); var obj = JSON.parse(pre[0].innerHTML); }
使用這種方法時需要注意,iframe有跨域限制,創建出來的iframe的地址如果和當前頁面地址不同源,會報錯。這種情況下,建議大家在iframe的onload函數中,再次向后端請求一個接口獲取文件地址,而不是直接去iframe里讀取。或者返回這樣的數據。
<script type="text/javascript">
window.top.window[callback](data)
</script>
callback是和前端約定好的名字,上傳完成后觸發該函數並返回后端數據。
第二種:使用formData上傳。
用js構造form表單的數據,簡單高效,但最低只兼容IE10,所以需要兼容IE9的童鞋們就略過這個方法吧。
html:
<input type='file'>
js:
var formData = new FormData(); formData.append("userid", userid); formData.append("signature", signature); formData.append("file", file); //file是blob數據 //再用ajax發送formData到服務器即可,注意一定要是post方式上傳
說明:第一種方法提到了創建多個type=‘hidden’的input來發送簽名數據,這兒可以用formData.append方法來代替該操作,避免了dom中有多個input的情況出現。最后將file數據也append到formData發送到服務器即可完成上傳。
優點:由於這種方式是ajax上傳,可以准確知道什么時候上傳完成,也可以方便地接收到回調數據。
缺點:兼容性差
第三種:使用fileReader讀取文件數據進行上傳。
HTML5的新api,兼容性也不是特別好,只兼容到了IE10。
var fr = new FileReader(); fr.readAsDataURL(file); fr.onload = function (event) { var data= event.target.result; //此處獲得的data是base64格式的數據 img.src = data; ajax(url,{data} ,function(){}) }
上面獲得的data可以用來實現圖片上傳前的本地預覽,也可以用來發送base64數據給后端然后返回該數據塊對應的地址。
優點: 同第二種
缺點:一次性發送大量的base64數據會導致瀏覽器卡頓,服務器端接收這樣的數據可能也會出現問題。