前段項目中有用到上傳的功能,用的angular-file-upload插件,功能還蠻強大的,界面也很漂亮。當時有個需求是醬紫。添加到上傳列表(還未上傳時)可以預覽圖片,如果滿意再上傳。很遺憾的說我沒搞出來,當時不知道h5 的file api,更不知道blob URL是什麼鬼。慫慫地就跟“大哥”商量把需求改成上傳後預覽,點擊預覽的時候請求後臺,返回服務器上的路徑,並打開,這樣肯定是ok的,但是與原需求不完全契合,feeling lost。
回家無意翻紅寶書,看到H5新增的,File Api這部分有file reader的新對象,更有對象URL(blob URL),這纔是這篇文章的主角,讓之前的欠缺的功能得到解決。
對象URL(blob URL)指的是引用保存在File或者Blob中數據的URL。使用對象URL的好處死可以不必把文件內容取到JavaScript中而直接使用文件內容。爲此,只要在需要文件內容的地方提供對象URL即可。要創建對象URL,可以使用window.URL.createObjectURL()方法,並傳入File或者Blob對象。這個函數的返回值是一個字符串,指向一塊內存的地址。因爲這個字符串是URL,所以在DOM中也能使用,上demo。
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<style>
button{display: none;float:right;}
</style>
</head>
<body>
<input type="file" id='files-list' multiple name=""><button>預覽下一張</button>
<div id='output'></div>
</body>
<script>
var filesList=document.getElementById('files-list');
var btn=document.getElementsByTagName('button')[0];
var output=document.getElementById('output');
var files=null;
var index=0;
filesList.addEventListener('change',function(event){
files=event.target.files,//取到files的對象並賦值。
console.log(files)
if(files.length>0){
btn.style.display='block';
}else{
btn.style.display='none';
}
btn.click();
})
btn.addEventListener('click',function(){
var num=files.length;
url=window.URL.createObjectURL(files[index]); //根據index創造對應的blob url對象
if(url){
if(/image/.test(files[index].type)){
output.innerHTML='<img src=\''+url+'\'>'
}else{
output.innerHTML="not an image"
}
}else{
output.innerHTML="your brower doesn"
}
if(index==num-1){//實現輪播
index=0;
}else{
index++;
}
})
</script>
</html>
通過以上方法,就能在真正上傳到服務器之前,實現預覽的效果。
但是在angularJs中<input type='file'>
和ngchange有衝突,所以需要醬紫來轉變一下<input type="file" id='files-list' ng-model="image" onchange='angular.element(this).scope().test(event)'>
(注:在controller中已定義test方法),具體bug解決在這裏
因爲只要代碼再引用對象URL,內存就不會釋放,所以如果不在需要相應數據,最好手動釋放。對應的方法是window.URL.revokeObjectURL()