關於前端上傳文件全面基礎掃盲貼(零)
關於前端上傳文件全面基礎掃盲貼(一) ----- XMLHttpRequest
關於前端上傳文件全面基礎掃盲貼(二) ----- File
關於前端上傳文件全面基礎掃盲貼(三) ----- FormData
關於前端上傳文件全面基礎掃盲貼(四) ----- FileReader
關於前端上傳文件全面基礎掃盲貼(五) ----- H5拖拽事件
關於前端上傳文件全面基礎掃盲貼(六) ----- 圖片上傳,旋轉,重繪,預覽等實戰(附DEMO)javascript
摘自上面來源,分析的挺好,我又無恥得搬下來了:css
使用FileReader
對象,web應用程序能夠異步的讀取存儲在用戶計算機上的文件(或者原始數據緩衝)內容,可使用File
對象或者Blob
對象來指定所要處理的文件或數據.其中File對象能夠是來自用戶在一個<input>元素上選擇文件後返回的FileList
對象,也能夠來自拖放操做生成的DataTransfer
對象,還能夠是來自在一個HTMLCanvasElement
上執行mozGetAsFile()方法後的返回結果.
在這裏做用就是當你上傳圖片以後,能夠直接從本地先讀取出原始數據,而後在頁面上展現出來,就是傳說中的預覽圖片功能,在上傳到後臺前就已經能先拿原始數據來使用了html
看看兼容性如何(舒適提示:下圖只表明支持程度,支持歸支持,不必定百分百支持,因此用到部分方法時不兼容時正常的)
前端
建立一個FileReader對象:java
var reader = new FileReader();
事件 | 描述 |
---|---|
onabort | 當讀取操做被停止時調用 |
onerror | 當讀取操做發生錯誤時調用 |
onload | 當讀取操做成功完成時調用 |
onloadend | 當讀取操做完成時調用,不論是成功仍是失敗.該處理程序在onload或者onerror以後調用 |
onloadstart | 當讀取操做將要開始以前調用 |
onprogress | 在讀取數據過程當中週期性調用 |
abort | 停止該讀取操做.在返回時,readyState屬性的值爲DONE.當該FileReader對象沒有在進行讀取操做時(也就是readyState屬性的值不爲LOADING時),調用abort()方法會拋出異常DOM_FILE_ABORT_ERR |
下面方法會開始讀取指定的Blob對象或File對象中的內容. 當讀取操做完成時,readyState屬性
的值會成爲DONE
,若是設置了onloadend
事件處理程序,則調用之.區別在於:web
屬性 | 描述 |
---|---|
readAsArrayBuffer | result屬性中將包含一個ArrayBuffer對象以表示所讀取文件的內容 |
readAsBinaryString | result屬性中將包含所讀取文件的原始二進制數據 |
readAsDataURL | result屬性中將包含一個data: URL格式的字符串以表示所讀取文件的內容.(這個就是實現咱們預覽的重要方法了!!!!!) |
readAsText | result屬性中將包含一個字符串以表示所讀取的文件內容 |
介紹到這裏就差很少了,接下來看看怎麼實現不提交後臺實現預覽圖片,這裏只展現這部分功能先segmentfault
<!doctype html> <html> <head> <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/> <title></title> <script type="text/javascript"> var oFReader = new FileReader(); oFReader.onload = function (oFREvent) { document .getElementById("uploadPreview") .src = oFREvent.target.result; }; function loadImageFile() { if (document.getElementById("uploadImage").files.length === 0) return; var oFile = document .getElementById("uploadImage") .files[0]; oFReader.readAsDataURL(oFile); } </script> </head> <body> <form name="uploadForm"> <img id="uploadPreview"/> <input id="uploadImage" type="file" name="myPhoto" onchange="loadImageFile();"/> </form> </body> </html>
你看,其實很簡單,沒什麼複雜代碼,只是須要的範圍比較廣,爲了一個上傳圖片已經摺騰了多少知識點了,還沒完呢...o(一︿一+)o瀏覽器
迴歸正題,說說幾個要點,首先看看代碼的document.getElementById("uploadImage")
出現了好幾回了,是否是好礙眼?是否是好想優化?是否是想爲何不把他放到一個變量存起來算了?
不行的,由於當你存一個變量以後再上傳文件,你就找不到FileReader對象了,詳情能夠參考一下我以前寫的關於Javascript基本類型和引用類型小知識app
而後oFReader.onload裏面的oFREvent就是你可以拿到的數據了,裏面大概長這樣子的,看的眼花繚亂,大家能夠慢慢挖掘異步
其中:
readyState: 0-尚未加載任何數據.1-數據正在被加載.2-已完成所有的讀取請求.
result: 返回文件的內容。只有在讀取操做完成後,此屬性纔有效,返回的數據的格式取決因而使用哪一種讀取方法來執行讀取操做的。
中間插播一則消息吧,圖中可看到一個result屬性的地址,那是一個base64 編碼.就是能夠將一副圖片數據編碼成一串字符串,使用該字符串代替圖像地址。
咱們所看到的網頁上的每個圖片,都是須要消耗一個 http 請求下載而來的,後面所以誕生的精靈圖就是基於這個問題纔出來,不過侷限性比較大,很難適用到全部項目
詳情能夠參考一下【前端攻略】:玩轉圖片Base64編碼
另外就是兼容問題,由於懶得一個個去驗證,就沒寫上去,不過查過資料放下來給大家,可能有用到,詳情能夠參考一下
對於 Chrome、Firefox、IE10 使用 FileReader
來實現。
對於 IE6~9 使用濾鏡 filter:progid:DXImageTransform.Microsoft.AlphaImageLoader
來實現。
<!doctype html> <html> <head> <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/> <title></title> <script type="text/javascript"> var loadImageFile = (function () { if (window.FileReader) { var oPreviewImg = null, oFReader = new window.FileReader(), rFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i; oFReader.onload = function (oFREvent) { if (!oPreviewImg) { var newPreview = document.getElementById("imagePreview"); oPreviewImg = new Image(); newPreview.appendChild(oPreviewImg); } oPreviewImg.src = oFREvent.target.result; }; return function () { var aFiles = document .getElementById("imageInput") .files; if (aFiles.length === 0) return; if (!rFilter.test(aFiles[0].type)) { alert("You must select a valid image file!"); return; } oFReader.readAsDataURL(aFiles[0]); } } else if (navigator.appName === "Microsoft Internet Explorer") { return function () { document .getElementById("imagePreview") .filters .item("DXImageTransform.Microsoft.AlphaImageLoader") .src = document .getElementById("imageInput") .value; } } })(); </script> <style type="text/css"> #imagePreview { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale); } </style> </head> <body> <input id="imageInput" type="file" name="myPhoto" onchange="loadImageFile();"/> <div id="imagePreview"></div> </body> </html>
沒有IE瀏覽器測試,因此不知道是否是有效,其實裏面看起來比我寫的那個複雜,實際上多了個檢驗格式:
rFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i;
IE上兼容寫法:
document.getElementById("imagePreview").filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = document.getElementById("imageInput").value;
因此不要怕,若是我錯了記得提醒下我啊。
目前爲止其實已經該說的都差很少覆蓋到了吧,動手能力強的話已經能夠根據教程寫一個實例出來的了。我看狀況要不要加一個實戰代碼作系列結尾。