一:FileList對象與file對象
FileList對象表示用戶選擇的文件列表,在HTML4中,file控件內只允許放置一個文件,但是到了HTML5中,通過添加multiple屬性,file控件內允許一次放置多個文件,控件內的每一個用戶選擇的文件都是一個file對象,而FileList對象是file對象的列表;
比如如下代碼:
選擇文件<input type="file" id="file" multiple size="80"/> <input type="button" onclick="ShowFileName();" value="文件上傳"/>
我們可以按住ctrl鍵選擇多個文件;
JS代碼如下:
function ShowFileName() { var files = document.getElementById("file").files; for(var i = 0; i < files.length; i+=1) { var file = files[i]; console.log(file); console.log(file.name); } }
我們先打印下file對象有哪些屬性,在safari截圖如下:

如上圖可以看到有文件名(name)屬性,文件大小(size)屬性,最后修改時間,還有type屬性等;
二:Blob對象
在HTML5中,新增一個Blob對象,代表原始二進制數據,我們上面提到的file對象也繼承了這個Blob對象;
Blob對象有2個屬性,size屬性表示一個Blob對象的字節長度,type屬性表示Blob的MIME類型,如果是未知類型,則返回一個空字符串。
如下代碼:
選擇文件<input type="file" id="file" multiple size="80" accept="image/*"/> <input type="button" onclick="ShowFileType();" value="顯示文件信息"/> 文件字節長度:<span id="size"></span><br/> 文件類型:<span id="type"></span>
JS代碼如下:
function ShowFileType() { var file = document.getElementById("file").files[0]; var size = document.getElementById("size"); var type = document.getElementById("type"); // 顯示文件字節長度 size.innerHTML = file.size; // 顯示文件類型 type.innerHTML = file.type; console.log(file); }
我們打印出file,如下圖所示:

三:FileReader對象
FileReader對象有5種方法,其中四種用於讀取文件,另一種用來讀取過程中斷,需要注意的是:無論讀取成功與失敗,方法並不會返回讀取結果,而是將結果保存在result屬性中。此對象也是異步的。
FileReader對象的方法如下:
readAsBinaryString(file): 這個方法將blob對象或文件中的數據讀取為二進制字符串,通常我們將它傳送到服務器端,服務器端可以通過這段字符串存儲文件。
readAsText(file,encoding): 以純文本形式讀取文件,將讀取到的文本保存在result屬性中,第二個參數用於指定編碼類型,可選的。
readAsDataURL(file): 讀取文件並將文件以數據URL的形式保存在result屬性中。
readAsArrayBuffer(file): 讀取文件並將一個包含文件內容的ArrayBuffer保存在result屬性中。
FileReader對象的事件如下:
onabort: 數據讀取中斷時觸發
onerror: 數據讀取出錯時觸發
onloadstart: 數據讀取開始時觸發
onprogress: 數據讀取中
onload: 數據讀取成功完成時觸發
onloadend: 數據讀取完成時觸發,無論成功或失敗。
我們可以先看看demo,如何使用FileReader對象中前面三個方法;注意:fileReader對象讀取的數據都保存在result中,如下代碼:
<p> <label>請選擇一個文件:</label> <input type="file" id="file" /> <input type="button" value="讀取圖像" onclick = "readAsDataURL()"/> <input type="button" value="讀取二進制數據" onclick = "readAsBinaryString()"/> <input type="button" value="讀取文本文件" onclick = "readAsText()"/> </p> <div id="result"></div>
JS代碼如下:
<script>
var result = document.getElementById("result");
if(typeof FileReader == 'undefined') {
result.innerHTML = "抱歉,你的瀏覽器不支持FileReader";
}
// 將文件以Data URL形式進行讀入頁面
function readAsDataURL(){
// 檢查是否為圖像類型
var simpleFile = document.getElementById("file").files[0];
if(!/image\/\w+/.test(simpleFile.type)) {
alert("請確保文件類型為圖像類型");
return false;
}
var reader = new FileReader();
// 將文件以Data URL形式進行讀入頁面
reader.readAsDataURL(simpleFile);
reader.onload = function(e){
console.log(this.result);
result.innerHTML = '<img src="'+this.result+'" alt=""/>';
}
}
// 將文件以二進制形式讀入頁面
function readAsBinaryString(){
// 檢查是否為圖像類型
var simpleFile = document.getElementById("file").files[0];
if(!/image\/\w+/.test(simpleFile.type)) {
alert("請確保文件類型為圖像類型");
return false;
}
var reader = new FileReader();
// 將文件以二進制形式進行讀入頁面
reader.readAsBinaryString(simpleFile);
reader.onload = function(e){
// 在頁面上顯示二進制數據
result.innerHTML = this.result;
}
}
// 將文件以文本形式讀入頁面中
function readAsText(){
var simpleFile = document.getElementById("file").files[0];
var reader = new FileReader();
// 將文件以文本形式讀入頁面中
reader.readAsText(simpleFile);
reader.onload = function(e){
result.innerHTML = this.result;
}
}
</script>
如上代碼,如果需要演示的話,可以復制代碼到文本編輯器去,預覽下即可,這里就不截圖了;但是如上代碼,在safari瀏覽器就不支持了~ 截圖如下:

四:btoa方法與atob方法
在HTML5中,btoa方法與atob方法來支持base64編碼,b可以被理解為一串二進制數據,a可以被理解為一個ASCLL碼字符串,btoa的使用方法如下:
var result = window.btoa(data);
該方法用於將一串字符串進行base64編碼處理,該方法使用一個參數,參數值由一串二進制數據組成的Unicode字符串,該方法返回編碼后的base64格式的字符串。
atob方法使用如下所示:
var result = window.atob(data);
該方法用於將一串經過base64編碼后的base64格式的字符串進行解碼處理,該方法使用一個參數,參數值為一串經過base64編碼后的字符串,方法返回經過解碼后的一串由二進制數據組成的Unicode字符串;
瀏覽器支持:firefox,chrome,opera10.5+及IE10+
什么時候使用btoa方法呢?
當服務器端數據庫中直接保存了是圖片的二進制數據及圖片文件的格式時,當我們需要根據此二進制數據來渲染圖片的時候非常有用;如下代碼:
<p> <label>請選擇一個文件:</label> <input type="file" id="file"/> <input type="button" value="讀取圖像" onclick = "readPicture()" id="btnReadPicture"/> </p> <div id="result"></div>
JS代碼如下:
if(typeof FileReader == 'undefined') { result.innerHTML = "抱歉,你的瀏覽器不支持FileReader"; } function readPicture(){ // 檢查是否為圖像類型 var simpleFile = document.getElementById("file").files[0]; if(!/image\/\w+/.test(simpleFile.type)) { alert("請確保文件類型為圖像類型"); return false; } var reader = new FileReader(); // 將文件以二進制文件讀入頁面中 reader.readAsBinaryString(simpleFile); reader.onload = function(f){ var result = document.getElementById("result"); var src = "data:" + simpleFile.type + ";base64," + window.btoa(this.result); result.innerHTML = '<img src ="'+src+'"/>'; } }
當我們選擇一張圖像的時候,點擊讀取圖像按鈕即可生成一張圖片,雖然此方法我們還可以使用我們上面介紹的readAsDataURL的方法也可以直接讀取圖像,但是當服務器中直接是保存的是二進制文件的話,我們可以直接使用btoa此方法生成圖片即可;
下面我們可以看看atob的demo如下:
我們可以使用canvas來繪制一張圖片后,點擊上傳圖片按鈕后,首先通過canvas元素的toDataURL()方法獲取該圖片的url地址,最后獲取該URL地址中的base64格式的字符串,最后使用atob方法將其解碼為一串二進制數據,並將該二進制數據提交到服務器端;如下代碼:
<input type="button" value="上傳圖片" onclick="imgSave()"/><br/> <canvas id="canvas" width="400" height="300"></canvas>
JS代碼如下:
<script>
var canvas;
function draw(id) {
canvas = document.getElementById(id);
var context = canvas.getContext('2d');
context.fillStyle = 'rgb(0,0,255)';
context.fillRect(0,0,canvas.width,canvas.height);
context.fillStyle = 'rgb(255,255,0)';
context.fillRect(10,20,50,50);
}
draw('canvas');
function imgSave(){
var data = canvas.toDataURL("image/png");
data = data.replace("data:image/png;base64,","");
var xhr = new XMLHttpRequest();
xhr.open("POST","uploadImg.php");
xhr.send(window.atob(data));
}
</script>
uploadImg.php自己寫;
下面我們來做一個本地圖片上傳前預覽效果,但是safari不支持,所以在做移動端的同學可能不好了,特別是在IOS6下就不支持哦,應該還有其他辦法可以解決的,我們可以看看百度的插件,網址如下:
http://fex.baidu.com/webuploader/demo.html
之前我是做了一個上傳本地圖片之前預覽效果,如下鏈接:
http://www.cnblogs.com/tugenhua0707/p/3568134.html
今天為了學習FileReader,我們可以再來學習下;之前的本地上傳圖片預覽的話,不支持IE10+, 且把頁面放在服務器端在IE下會有bug,如下所示:

如上所示,在IE下 這個方法 document.selection.createRange() 不支持,因此為了修復這個bug和在IE10+以上的話,今天又特意研究了下, 在file控件下獲取焦點情況下 document.selection.createRange() 將會拒絕訪問,所以我們要失去下焦點。我們可以再加一句代碼就可以支持了 file.blur();
IE10+的bug的話,我們可以使用html5的上面介紹的文件API來解決,先判斷是不是IE,如果是的話,且小於10的話,使用濾鏡的方法解決圖片上傳的問題,如果是其他瀏覽器的話,就使用html5的文件上傳方法;但是safari沒有處理好,原因是safari不支持html5的fileReader的API,所以如果在移動端開發的圖片,如果需要兼容IOS6和6+的話,請注意一下,並不支持~ 當然如果大家有更好的方案來支持IOS6的話,請留言,可以一起總結,一起學習~
五:上傳圖片之前預覽效果demo(Safari不兼容)
1. 在標准瀏覽器下(IE10+)使用HTML5中文件API即可解決上傳圖片前預覽效果;在這里有2中方案可以解決,第一種是使用文件API,如下代碼:
function html5Reader(file) { var file = file.files[0]; var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function(e){ var pic = document.getElementById("img"); pic.src=this.result; } }
2. 第二種方案是使用 URL.createObjectURL(fileObj) 這個方法和canvas技術, 我們先來看看 支持這個 URL.createObjectURL(fileObj) 的瀏覽器有哪些,我們可以點擊下面的連接查看:
http://caniuse.com/#search=createObjectURL/
實現代碼如下:
function html5Reader(file) { var fileObj = file.files[0], img = document.getElementById("img"); // URL.createObjectURL safari不支持 img.src = URL.createObjectURL(fileObj); img.onload =function() { var data = getBase64Image(img); console.log(data); // 打印出base64編碼 } } function getBase64Image(img) { var canvas = document.createElement("canvas"); canvas.width = img.width; canvas.height = img.height; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, img.width, img.height); var ext = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase(); var dataURL = canvas.toDataURL("image/"+ext); return dataURL;
}
HTML代碼如下:
<input type="file" id="logo" name="logo" accept="image/*"> <img src= '' id="img"/> <div id="btn" style="margin-top:50px;font-size:40px;">btn</div> <canvas id="myCanvas"></canvas>
所有的JS代碼如下:
<script>
var EventUtil = {
addHandler: function(element,type,handler) {
if(element.addEventListener) {
element.addEventListener(type,handler,false);
}else if(element.attachEvent) {
element.attachEvent("on"+type,handler);
}else {
element["on" +type] = handler;
}
}
};
var btn = document.getElementById("btn");
var pic = document.getElementById("img");
function getBase64Image(img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
var ext = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase();
var dataURL = canvas.toDataURL("image/"+ext);
return dataURL;
}
var ua = navigator.userAgent.toLowerCase();
EventUtil.addHandler(btn,'click',function(){
var file = document.getElementById("logo");
var ext=file.value.substring(file.value.lastIndexOf(".")+1).toLowerCase();
// gif在IE瀏覽器暫時無法顯示
if(ext!='png'&&ext!='jpg'&&ext!='jpeg'){
alert("圖片的格式必須為png或者jpg或者jpeg格式!");
return;
}
if(/msie ([^;]+)/.test(ua)) {
var lowIE10 = RegExp["$1"]*1;
if(lowIE10 == 6){
// IE6瀏覽器設置img的src為本地路徑可以直接顯示圖片
file.select();
// 在file控件下獲取焦點情況下 document.selection.createRange() 將會拒絕訪問,所以我們要失去下焦點。
file.blur();
var reallocalpath = document.selection.createRange().text;
pic.src = reallocalpath;
}else if(lowIE10 > 6 && lowIE10 < 10){
// IE7~9 IE10+按照html5的標准去處理
file.select();
// 在file控件下獲取焦點情況下 document.selection.createRange() 將會拒絕訪問,所以我們要失去下焦點。
file.blur();
var reallocalpath = document.selection.createRange().text;
// 非IE6版本的IE由於安全問題直接設置img的src無法顯示本地圖片,但是可以通過濾鏡來實現
pic.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src=\"" + reallocalpath + "\")";
// 設置img的src為base64編碼的透明圖片 取消顯示瀏覽器默認圖片
pic.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
}else if(lowIE10 >= 10) {
html5Reader(file);
}
}else {
html5Reader(file);
}
});
function html5Reader(file) {
var fileObj = file.files[0],
img = document.getElementById("img");
// URL.createObjectURL safari不支持
img.src = URL.createObjectURL(fileObj);
img.onload =function() {
var data = getBase64Image(img);
console.log(data); // 打印出base64編碼
}
/*
var file = file.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e){
var pic = document.getElementById("img");
pic.src=this.result;
}*/
}
</script>
