在html4的年代,咱們若是要在網頁上呈現一張用戶本地的圖片,須要用戶先把圖片上傳到服務器,再根據服務器提供的圖片地址把圖片下載下來,才能把圖片在網頁上呈現出來。這一來二往,起碼已經費了兩倍於這張圖片的流量了,更別說服務器爲了存儲這張圖片所花費的資源以及用戶上傳錯了圖片的冤枉成本(由於在html4時代,用戶選擇好圖片後,每每只能看到圖片的文件名,而沒法經過預覽圖來進一步確認這張圖片是否就是本身想要上傳的)。 html5提供了新玩法,光靠瀏覽器,就能夠對本地的(其實也能夠是遠程的)文件(主要是圖片)進行呈現、讀取、處理等操做,而這一切,則是經過html5 file api來實現的。html
首先是數據結構,html5定義了一個file對象類型來表示文件,每一個file對象對應一個文件。file對象有3個屬性:name、size、type。name是不包含路徑的文件名,size是以字節爲單位的文件體積大小,type則是文件的MIME(例如image/jpg)。 file對象不單獨存在,而是以數組形式,存在一個名爲FileList的數組中。那麼,如何拿到這個FileList數組呢?目前,html5有兩個途徑能夠拿到FileList,一是經過file類型的input,二是經過拖放操做的drop事件。html5
<input id="file-input" type="file" />
複製代碼
或html5新增的可進行文件多選的multiple屬性:jquery
<input id="file-input" type="file" multiple />
複製代碼
通常,咱們都是給input:file綁上一個onchange事件,以便在用戶選定文件後,立刻進行讀取文件等下一步操做:canvas
//原生js
var inputElement = document.getElementById("file-input");
inputElement.addEventListener("change", handleFiles, false);
function handleFiles() {
var fileList = this.files;
}
//jquery版
$('#file-input').on('change', function() {
var fileList = this.files;
});
複製代碼
首先要設定一個可供拖放的區域:api
<div id="dropbox" style="width: 200px;height: 200px;"></div>
複製代碼
另外,爲了能觸發drop事件,咱們必須阻止dragenter和dragover事件的默認行爲:數組
var dropbox;
dropbox = document.getElementById("dropbox");
dropbox.addEventListener("dragenter", dragenter, false);
dropbox.addEventListener("dragover", dragover, false);
dropbox.addEventListener("drop", drop, false);
function dragenter(e) {
e.stopPropagation();
e.preventDefault();
}
function dragover(e) {
e.stopPropagation();
e.preventDefault();
}
複製代碼
而後,咱們就能夠在drop事件的callback中,獲取到fileList:瀏覽器
function drop(e) {
e.stopPropagation();
e.preventDefault();
var dt = e.dataTransfer;
var files = dt.files;
handleFiles(files);
}
複製代碼
html5提供了兩個方案:FileReader和ObjectUrl。服務器
首先須要實例化FileReader對象:數據結構
var reader = new FileReader();
複製代碼
利用FileReader讀取file對象是一個異步的過程,咱們須要先爲FileReader設置好load事件的callback,告知FileReader在讀取到file對象的數據後應該進行什麼進一步的操做:異步
reader.onload = function(e) {
document.getElementById("image").src = e.target.result;
}
複製代碼
上面這段代碼的意思是,FileReader讀取到圖片的數據後,把數據(DataUrl)放到的src屬性裏。 最後,就是經過FileReader不一樣的方法,來決定讀取file對象數據後用什麼數據格式來存放,並實施讀取:
ObjectURL至關於文件的一個臨時路徑,此臨時路徑可隨時生成、隨時釋放,在本地瀏覽器使用起來時,與普通的url無異。 以把一張本地圖片顯示在頁面上爲例:
var img = document.createElement("img");
img.src = window.URL.createObjectURL(file);
複製代碼
此時,src形如:blob:http://test.local.com/e03e8bbf-66ce-4fea-a8c8-772f9fdb4d40
用這個src就能讓瀏覽器從本地讀取圖片。 這種方案相對用FileReader生成圖片的base64編碼並放到的src裏來講,性能有了很大的提高。
比較這兩種讀取File對象的方案,FileReader適合用來上傳文件,而ObjectURL則適合直接在瀏覽器進行操做,而後操做後再把處理後的數據進行上傳,例如利用canvas截圖或進行圖片壓縮等。固然,這一切都是要考慮兼容性的。