上傳咱們通常都是用「input[type=file]」控件。當你用此控件時,你就受權了網頁和服務器訪問對應的文件,就能夠獲得File對象。javascript
友情提示在,在Android手機webview中,是不支持上傳文件的,網上說是修改Android端的代碼,但我沒試過,咱們這邊是使用客戶端提供的接口來實現上傳的。html
下面的示例代碼能夠在這裏查看到。html5
該屬性代表了服務器端可接受的文件類型,能夠限制你手機選擇相關的文件,若是限制多個,能夠用逗號分割,下面的代碼就表示只能選擇圖片與音頻相關的文件:java
<input accept="image/*,audio/*" type="file"/>
在移動端,點擊後會讓你選擇拍照或相冊,仍是蠻高大上的。下圖是UC瀏覽器中:node
通常選擇文件都會使用「change」事件,下面的代碼就是綁定了change事件,彈出文件大小:web
var upload = document.getElementById('upload'); upload.addEventListener('change', function() { var file = upload.files[0]; alert(file.size); }, false);
1) 有些手機瀏覽器在點擊的時候,會彈出鍵盤選擇,我用onfocus="this.blur()",來強制失去焦點。canvas
<input type="file" id="upload" onfocus="this.blur()"/>
2) 當選擇過一次後,再次選擇同一個文件,「change」事件不會觸發,由於value沒有改變,在網上看到個方法,我尚未在實際項目中使用,兼容性有待考證。api
使用「Node.cloneNode」複製上傳元素,再用「Node.replaceChild」替換節點。數組
這裏注意下:克隆一個元素節點會拷貝它全部的屬性以及屬性值,但不會拷貝那些使用addEventListener()方法或者node.onclick = fn用JavaScript動態綁定的事件。瀏覽器
upload.addEventListener('change', function() { var upload = document.getElementById('upload'); //每次要動態獲取 var file = upload.files[0]; console.log(file.size); //解決上傳相同文件不觸發onchange事件 var clone = upload.cloneNode(true); clone.onchange = arguments.callee; //克隆不會複製動態綁定事件 clone.value = ''; upload.parentNode.replaceChild(clone, upload); }, false);
用戶所選擇的文件都存儲在了一個FileList對象上,其中每一個文件都對應了一個File對象
File對象負責處理那些以文件形式存在的二進制數據,也就是操做本地文件。
File對象是Blob【下面會提到】的特殊類型,即大塊的二進制數據,File對象的尺寸及類型等屬性都繼承自Blob。
1)File對象能夠經過3種方式獲取:
1. <input>元素上選擇文件後返回的FileList對象中的成員
2. 拖放操做【Drag或Drop】生成的 DataTransfer對象內files屬性中的成員
3. HTMLCanvasElement上執行mozGetAsFile()方法後的返回結果
document.getElementById('upload').files[0]//選取第一個文件對象
2)File對象有9個屬性,這裏就只介紹3個:
1. name:當前File對象所引用文件的文件名,不包括路徑,只讀。
2. size:文件大小,單位爲字節,只讀的64位整數.
3. type:MIME類型,只讀字符串,若是類型未知,則返回null。有些移動端的瀏覽器明明選擇了圖片,返回的倒是null,很是坑。
還有3個非標準的方法:getAsBinary()、getAsDataURL()和getAsText(in DOMString encoding)。
這3個方法如今已通過時,如今用FileReader對象中的方法來取代。
web應用程序能夠異步的讀取存儲在用戶計算機上的文件(或者原始數據緩衝)內容,可使用File對象或者Blob對象來指定所要處理的文件或數據。
1) readAsArrayBuffer():在返回的result屬性中將包含一個ArrayBuffer對象【緩衝數組,是一種用於呈現通用、固定長度的二進制數據的類型】以表示所讀取文件的內容
Blob能夠「append」,ArrayBuffer數據。ArrayBuffer存在的意義就是做爲數據源提早寫入在內存中,就是提早釘死在某個區域,長度也固定。
2) readAsBinaryString():result屬性中將包含所讀取文件的原始二進制數據
3) readAsDataURL():result屬性中將包含一個data: URL格式的字符串以表示所讀取文件的內容
4) readAsText():result屬性中將包含一個字符串以表示所讀取的文件內容
下面的代碼是獲取data:URL,能夠將返回的result內容賦值給img的src,用於預覽等操做。
var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function(e) { var img = new Image(); img.src = this.result; console.log(this.result); };
console.log(this.result)內容以下:
URL對象是硬盤上指向文件的URL。上面的例子中獲取圖片的引用,經過讀取data URI,data URI是個一大串的字符。
圖片本來就在硬盤上,還要轉換成另外一個格式再用,有點繞了,徹底能夠直接引用文件的URL,下面是兩個方法:
1) URL.createObjectURL():接收一個文件的引用(File或Blob對象)返回一個URL對象
2) URL.revokeObjectURL():銷燬建立的URL
var url = URL.createObjectURL(file); var img = new Image(); img.src = url; img.onload = function(e) { window.URL.revokeObjectURL(this.src); //銷燬 } console.log(url);
console.log(url)內容以下:
在移動端須要作個兼容性判斷:
window.URL = window.URL || window.webkitURL;
Blob(binary large object)對象表明了一段二進制數據,就是一個包含只讀原始數據的類文件對象。
File接口基於Blob,繼承了Blob的功能,而且擴展支持了用戶計算機上的本地文件。
1)建立Blob對象的4種方法:
1. 調用Blob構造函數
2. 使用一個已有Blob對象上的slice()方法切出另外一個Blob對象
3. 調用canvas對象上的toBlob方法
4. 過氣的方法,經過BlobBuilder接口建立,但兼容性很差,而且現有的BlobBuilder實現都是帶前綴的
2)利用Blob對象,生成可下載文件
var blob = new Blob(["pwstrick"]);//數組中添加DOMString對象 var a = document.createElement("a"); a.href = URL.createObjectURL(blob);//建立URL對象 a.download = "test.txt";//HTML5新屬性 a.textContent = "test"; document.getElementsByTagName('body')[0].appendChild(a);
生成一個「a」標籤,而且點擊這個連接,能夠下載一個txt文本,內容是「pwstrick」。
3)經過slice方法,將二進制數據按照字節分塊,返回一個新的Blob對象
upload.addEventListener('change', function() { var upload = document.getElementById('upload'); //每次要動態獲取 var file = upload.files[0]; var start = 0; var chunk = 1024 * 10; //10KB var end = start + chunk; var size = file.size; while (start < size) { segment(file, start, end); start = end; end = start + chunk; if (end > size) { end = size; } } }, false); function segment(file, start, end) { var reader = new FileReader(); reader.onload = function(evt) { console.log(['Read bytes: ', start, ' - ', end].join('')); }; var blob = file.slice(start, end); reader.readAsBinaryString(blob); }
XMLHttpRequest Level 2添加了一個新的接口FormData。
利用FormData對象,可使用鍵值對來模擬一個完整的表單,而後使用XMLHttpRequest發送這個"表單"。
使用FormData的最大優勢就是咱們能夠異步上傳一個二進制文件。
var formData = new FormData(); formData.append("name", "value");//普通鍵值對 formData.append("blob", blob); //傳遞一個blob對象 formData.append("file", file); //傳遞一個file對象 var oReq = new XMLHttpRequest(); oReq.open("POST", "http://xx.com"); oReq.send(formData);
參考資料:
https://developer.mozilla.org/zh-CN/docs/Using_files_from_web_applications 在web應用中使用文件
http://javascript.ruanyifeng.com/htmlapi/file.html 文件和二進制數據的操做
http://www.iunbug.com/archives/2012/06/04/208.html [譯]JavaScript文件操做基礎
http://www.iunbug.com/archives/2012/06/05/254.html [譯]JavaScript文件操做URL對象
http://www.html5rocks.com/zh/tutorials/file/dndfiles/ 經過 File API 使用 JavaScript 讀取文件