File 接口提供有關文件的信息,並容許網頁中的JavaScript訪問其內容。
File對象能夠用來獲取某個文件的信息,還能夠用來讀取這個文件的內容。一般狀況下,File對象是來自用戶在一個 <input>
元素上選擇文件後返回的FileList對象,也能夠是來自由拖放操做生成的 DataTransfer對象。javascript
用戶在選擇一個或者多個文件後,能夠經過File API訪問這些File對象,這些對象被包含在一個FileList對象中。全部type爲file的input都有一個files屬性,經過Element.files能夠返回FileList對象。html
<body> <input type="file" id="fileInput" name="file" multiple="multiple" accept="image/*"> <script> var fileInput = document.querySelector("#fileInput"); fileInput.addEventListener("change", function (event) { var file = fileInput.files[0]; console.log(fileInput.files) }, false) </script> </body>
files有一個length屬性和item方法,能夠經過files[index]或者files.item(index)獲取咱們選擇的file對象。每一個File對象中包含了文件的一些詳細信息:html5
根據size屬性換算爲咱們習慣的文件大小單位:java
function bytesToSize(bytes) { if (bytes === 0) return '0 B'; var k = 1024, sizes = ['B','KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; // Math.log() 返回數字的天然對數 log(b)/log(a)=loga(b)) 換底公式 log以a爲底b的對數 // Math.floor(x) -- 向下取整,返回小於或等於x的值 // Math.pow(x,y) -- 返回以x的y次冪,等同於x^y的數值表達式 var i = Math.floor(Math.log(bytes) / Math.log(k)); return (bytes / Math.pow(k, i)).toFixed(1) + ' ' + sizes[i]; }
FileReader 對象容許Web應用程序異步讀取存儲在用戶計算機上的文件(或原始數據緩衝區)的內容,使用 File 或 Blob 對象指定要讀取的文件或數據
其中File對象能夠是來自用戶在一個<input>元素上選擇文件後返回的FileList對象,也能夠來自拖放操做生成的 DataTransfer對象,還能夠是來自在一個HTMLCanvasElement上執行mozGetAsFile()方法後返回結果
先來看一個例子:git
<body> <div id="dropbox" class="dropbox"> <div class="area">拖動圖片到這裏</div> </div> <div id="preview"></div> <script type="text/javascript"> var dropbox = document.querySelector("#dropbox"); var preview = document.querySelector("#preview"); dropbox.addEventListener("dragenter", function (e) { e.stopPropagation(); e.preventDefault(); }, false); dropbox.addEventListener("dragover", function (e) { e.stopPropagation(); e.preventDefault(); }, false); dropbox.addEventListener("drop", function (e) { e.stopPropagation(); e.preventDefault(); var dt = e.dataTransfer; var files = dt.files; for (var i = 0; i < files.length; i++) { var file = files[i]; var imageType = new RegExp("^image\/"); if (!imageType.test(file.type)) continue; // 填充選擇的圖片到展現區 var img = document.createElement("img"); img.classList.add("obj"); img.file = file; preview.appendChild(img); // 讀取File對象中的內容 var reader = new FileReader(); reader.onload = (function (aImg) { return function (e) { aImg.src = e.target.result; }; })(img); reader.readAsDataURL(file); } }, false); </script> </body>
在上面的例子中,預覽圖片的src使用了」data:image/png;base64,xxxxxxxxxxxxx」這種形式的字符串(base64),這種字符串叫作DataURI對象,容許將一個小文件進行編碼後嵌入到另一個文檔裏,格式爲:github
data:[<MIME type>][;charset=<charset>][;base64],<encoded data>
這個字符串能夠分爲三部分,即聲明:參數+數據,逗號左邊的是各類參數,右邊的是數據。ajax
咱們能夠經過FileReader 的readAsDataURL方法得到文件的DataURIsegmentfault
開始讀取指定的Blob對象或File對象中的內容。當讀取操做完成時,readyState屬性的值會成爲DONE,若是設置了onloadend事件處理程序,則調用之。同時,result屬性中將包含一個data:URL格式的字符串以表示所讀取文件的內容。
var reader = new FileReader(); reader.onload = function() { console.log(this.result); } reader.readAsDataURL(file);
除了可使用base64字符串做爲內容的DataURI將一個文件嵌入到另一個文檔裏,還可使用URL對象。URL對象用於生成指向File對象或Blob對象的URL
URL.createObjectURL() 數組
該方法會建立一個 DOMString,其中包含一個表示參數中給出的對象的URL。這個 URL 的生命週期和建立它的窗口中的 document 綁定。這個新的URL 對象表示指定的 File 對象或 Blob 對象。瀏覽器
objectURL = URL.createObjectURL(blob);
blob
是用來建立 URL 的 File 對象或者 Blob 對象
URL.revokeObjectURL()
該方法用來釋放一個以前經過調用 URL.createObjectURL() 建立的已經存在的 URL 對象。當你結束使用某個 URL 對象時,應該經過調用這個方法來讓瀏覽器知道再也不須要保持這個文件的引用了。
window.URL.revokeObjectURL(objectURL);
objectURL
是一個 DOMString,表示經過調用 URL.createObjectURL() 方法產生的 URL 對象
一樣以拖拽上傳圖片預覽爲例子:
<body> <div id="dropbox" class="dropbox"> <div class="area">拖動圖片到這裏</div> </div> <div id="preview"></div> <script type="text/javascript"> var dropbox = document.querySelector("#dropbox"); var preview = document.querySelector("#preview"); dropbox.addEventListener("dragenter", function (e) { e.stopPropagation(); e.preventDefault(); }, false); dropbox.addEventListener("dragover", function (e) { e.stopPropagation(); e.preventDefault(); }, false); dropbox.addEventListener("drop", function (e) { e.stopPropagation(); e.preventDefault(); console.log(e) var dt = e.dataTransfer; var files = dt.files; for (var i = 0; i < files.length; i++) { var file = files[i]; var imageType = new RegExp("^image\/"); if (!imageType.test(file.type)) { console.log(1) continue; } // 填充選擇的圖片到展現區 var img = document.createElement("img"); img.classList.add("obj"); img.file = file; img.src = window.URL.createObjectURL(file); preview.appendChild(img); } }, false); </script> </body>
實際上上文的File對象只是 Blob 對象的一個更具體的版本,Blob對象 存儲着大量的二進制數據,而且 Blob 的 size 和 type 屬性,都會被 File 對象所繼承。一樣FileReader對象也能夠從Blob對象中讀取數據。
一個 Blob對象表示一個不可變的, 原始數據的相似文件對象。Blob表示的數據不必定是一個JavaScript原生格式。 File 接口基於Blob,繼承 blob功能並將其擴展爲支持用戶系統上的文件。
使用 Blob()
構造函數能夠構造一個Blob從其餘非blob對象和數據。要建立一個包含另外一個blob的數據子集的blob,使用 slice()
方法。
Blob構造函數,接受兩個參數。第一個參數是一個包含實際數據的數組,第二個參數是數據的類型,這兩個參數都不是必需的。數組元素能夠是任意多個的ArrayBuffer,ArrayBufferView (typed array), Blob,或者 DOMString對象。例如:
var arr = ['<h1>hello world</h1>']; var blob = new Blob(arr, { "type" : "text/xml" }); // the blob console.log(blob);
Blob對象的slice方法,將二進制數據按照字節分塊,返回一個新的Blob對象
var newBlob = oldBlob.slice(startingByte, endindByte);
返回一個新的 Blob 對象,包含了源 Blob 對象中指定範圍內的數據。
使用XMLHttpRequest對象,將大文件分割上傳:
function upload(blobOrFile) { var xhr = new XMLHttpRequest(); xhr.open('POST', '/server', true); xhr.onload = function(e) { ... }; xhr.send(blobOrFile); } document.querySelector('input[type="file"]').addEventListener('change', function(e) { var blob = this.files[0]; const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk sizes. const SIZE = blob.size; var start = 0; var end = BYTES_PER_CHUNK; while(start < SIZE) { upload(blob.slice(start, end)); start = end; end = start + BYTES_PER_CHUNK; } }, false);
/** * dataURL to blob, ref to https://gist.github.com/fupslot/5015897 * @param dataURI * @returns {Blob} */ function dataURItoBlob(dataURI) { var byteString = atob(dataURI.split(',')[1]); var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; var ab = new ArrayBuffer(byteString.length); var ia = new Uint8Array(ab); for (var i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } return new Blob([ab], {type: mimeString}); } // atob() 將base64解碼 // btoa() 將字符串轉碼爲base64 var str = 'javascript'; window.btoa(str) //轉碼結果 "amF2YXNjcmlwdA==" window.atob("amF2YXNjcmlwdA==") //解碼結果 "javascript"
用FormData對象,咱們能夠經過JavaScript用一些鍵值對來模擬一系列表單控件,咱們還可使用XMLHttpRequest的send()方法來異步的提交這個」表單」.比起普通的ajax,使用FormData的最大優勢就是咱們能夠異步上傳一個二進制文件
FormData對象的做用相似於jQuery裏面的 serialize()
方法,serialize()
做用就是表單序列化,也就是以查詢字符串形式得到類表單post/get的數據給Ajax請求,例如:userid=123&username=zxx。
new FormData (form? : HTMLFormElement)
form 參數可選,是一個HTML表單元素,能夠包含任何形式的表單控件,包括文件輸入框。
append() 給當前FormData對象添加一個鍵/值對
void append(DOMString 鍵, Blob 值, [可選] DOMString 文件名); void append(DOMString 鍵, DOMString 值);
<form id="uploadForm" enctype="multipart/form-data"> <input id="file" type="file" name="file"/> <button id="upload" type="button">upload</button> </form>
$.ajax({ url: '/upload', type: 'POST', cache: false, data: new FormData($('#uploadForm')[0]), processData: false, contentType: false }).done(function(res) { }).fail(function(res) {});
var fd = new FormData(); // 構造FromData對象 var blob = dataURItoBlob(dataURI); // 將base64轉爲二進制blob對象 fd.append('file', blob); $.ajax({ type: 'POST', url: '/upload', data: fd, processData: false, // 不會將 data 參數序列化字符串,必須false contentType: false, // 根據表單 input 提交的數據使用其默認的 contentType,必須false xhr: function() { var xhr = new window.XMLHttpRequest(); xhr.upload.addEventListener("progress", function(evt) { if (evt.lengthComputable) { var percentComplete = evt.loaded / evt.total; console.log('進度', percentComplete); } }, false); return xhr; } }).success(function (res) { // 拿到提交的結果 }).error(function (err) { console.error(err); });
小青年博客
基於html5 File API的文件操做
MDN
理解DOMString、Document、FormData、Blob、File、ArrayBuffer數據類型
利用FileReader和FormData實現圖片預覽和上傳
轉: https://blog.csdn.net/mr_wuch/article/details/70141674