目錄
- Blob及其屬性和方法
- File
- FileReader及其屬性和方法
- URL及其屬性和方法
歷史上,JavaScript
無法處理二進制數據。如果一定要處理的話,只能使用 charCodeAt()
方法,一個個字節地從文字編碼轉成二進制數據,還有一種辦法是將二進制數據轉成 Base64
編碼,再進行處理。這兩種方法不僅速度慢,而且容易出錯。ECMAScript 5
引入了 Blob
對象,允許直接操作二進制數據。
Blob
對象是一個代表二進制數據的基本對象,在它的基礎上,又衍生出一系列相關的API,用來操作文件。
File
對象:負責處理那些以文件形式存在的二進制數據,也就是操作本地文件;FileList
對象:File
對象的網頁表單接口;FileReader
對象:負責將二進制數據讀入內存內容;URL
對象:用於對二進制數據生成URL
Blob
Blob
(Binary Large Object) 對象代表了一段二進制數據,提供了一系列操作接口。其他操作二進制數據的API(比如 File
對象),都是建立在 Blob
對象基礎上的,繼承了它的屬性和方法。
創建 Blob 類型的對象
生成 Blob
對象有兩種方法:一種是使用 Blob
構造函數,另一種是對現有的 Blob
對象使用 slice
方法切出一部分。
1. new Blob()
Blob
構造函數,接受兩個參數。第一個參數是一個包含實際數據的數組,這個數組中的元素可以爲 DOMString
,或者 ArrayBuffer
,第二個參數是數據的類型,這兩個參數都不是必需的。
var domstring = '<div>Hello world</div>';
var blob1 = new Blob([domstring], {type: 'text/html'});
var buffer = new ArrayBuffer(8);
var blob2 = new Blob([buffer], {type: 'text/plain'});
2. blob.slice()
此方法返回一個新的 Blob
對象,包含了原 Blob
對象中指定範圍內的數據
Blob.slice(start:number, end:number, contentType:string)。start:開始索引,默認爲0;end:截取結束索引(不包括end);contentType:新Blob的MIME類型,默認爲空字符串
Blob 對象的屬性
- Blob.size:
Blob
對象中所包含數據的大小(字節)。該屬性爲只讀; - Blob.type: 一個字符串,表明該
Blob
對象所包含數據的MIME
類型。如果類型未知,則該值爲空字符串。該屬性爲只讀
Blob 應用實例
下面是一個使用XMLHttpRequest對象,將大文件分割上傳的例子。
function upload(blobOrFile) {
let xhr = new XMLHttpRequest();
xhr.open('post', '/server', true);
xhr.onload = function(e) {};
xhr.send(blobOrFile);
}
document.querySelctor('input[type="file"]').addEventListener('change', function() {
let blob = this.files[0];
const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk size
const SIZE = blob.size;
let start = 0;
let end = BYTES_PER_CHUNK;
while(start < end) {
upload(blob.slice(start, end));
start = end;
end = start + BYTES_PER_CHUNK;
}
}, false);
File
File
接口提供有關文件的信息,並允許網頁中的JavaScript
訪問其內容。
File
對象可以用來獲取某個文件的信息,還可以用來讀取這個文件的內容。通常情況下, File
對象是來自用戶在一個 <input>
元素上選擇文件後返回的 FileList
對象,也可以是來自由拖放操作生成的 DataTransfer
對象。
用戶在選擇一個或者多個文件後,可以通過 File
API訪問這些File
對象,這些對象被包含在一個 FileList
對象中。所有 type
爲 file
的 input
都有一個 files
屬性,通過 Element.files
可以返回 FileList
對象。
<body>
<input type="file" id="fileInput" name="file" multiple="multiple" accept="image/*">
<script>
var fileInput = document.querySelector("#fileInput");
fileInput.addEventListener("change", function (event) {
// 文件列表對象
var fileList = this.files;
// 獲取第一個文件
var file = fileInput.files[0];
// 文件名
var filename = file.name;
// 文件大小
var filesize = file.size;
//文件的 MIME 類型,如果分辨不出類型,則爲空字符串,該屬性只讀
var type = file.type;
// 文件的上次修改時間,格式爲時間戳
var lastModified = file.lastModified;
// 文件的上次修改時間,格式爲 Date 對象實例
var lastModifiedDate = file.lastModifiedDate;
}, false);
console.log(fileList);
// 上傳了兩個文件,FileList {0: File, 1: File, length: 2}
</script>
</body>
File 對象的屬性:
- name:文件名,該屬性只讀。
- size:文件大小,單位爲字節,該屬性只讀。
- type:文件的 MIME 類型,如果分辨不出類型,則爲空字符串,該屬性只讀。
- lastModified:文件的上次修改時間,格式爲時間戳。
- lastModifiedDate:文件的上次修改時間,格式爲 Date 對象實例
File 對象的方法:
File 接口沒有定義任何方法,但是它從 Blob 接口繼承了以下方法:
Blob.slice([start[, end[, contentType]]])
返回一個新的 Blob
對象,它包含有源 Blob
對象中指定範圍內的數據。
FileReader
我們知道 Blob
對象只是二進制數據的容器,本身並不能操作二進制,FileReader
對象就是專門操作二進制數據的,FileReader
主要用於將文件內容讀入內存,通過一系列異步接口,可以在主線程中訪問本地文件。
構造函數
var reader = new FileReader();
屬性
- FileReader.error:表示在讀取文件時發生的錯誤;
- FileReader.readyState:0-還沒有加載任何數據, 1-數據正在被加載, 2-已完成全部的讀取請求;
- FileReader.result:文件的內容。該屬性僅在讀取操作完成後纔有效,數據的格式取決於使用哪個方法來啓動讀取操作。
事件
- FileReader.onabort:處理
abort
事件。該事件在讀取操作被中斷時觸發; - FileReader.onerror:處理
error
事件。該事件在讀取操作發生錯誤時觸發; - FileReader.onload:處理
load
事件。該事件在讀取操作完成時觸發; - FileReader.onloadstart:處理
loadstart
事件。該事件在讀取操作開始時觸發; - FileReader.onloadend:處理
loadend
事件。該事件在讀取操作結束時(要麼成功,要麼失敗)觸發; - FileReader.onprogress:處理
progress
事件。該事件在讀取Blob
時觸發
方法
- FileReader.abort():中止讀取操作。在返回時,
readyState
屬性爲DONE; - FileReader.readAsArrayBuffer():開始讀取指定的
Blob
中的內容, 一旦完成,result
屬性中保存的將是被讀取文件的ArrayBuffer
數據對象; - FileReader.readAsBinaryString():開始讀取指定的
Blob
中的內容。一旦完成,result
屬性中將包含所讀取文件的原始二進制數據, 該方法將文件讀取爲二進制字符串,通常我們將它傳送到後端,後端可以通過這段字符串存儲文件; - FileReader.readAsDataURL():開始讀取指定的
Blob
中的內容。一旦完成,result
屬性中將包含一個data: URL
格式的字符串以表示所讀取文件的內容; - FileReader.readAsText():開始讀取指定的
Blob
中的內容。一旦完成,result
屬性中將包含一個字符串以表示所讀取的文件內容, 該方法有兩個參數,其中第二個參數是文本的編碼方式,默認值爲UTF-8
。這個方法非常容易理解,將文件以文本方式讀取,讀取的結果即是這個文本文件中的內容。
實際應用
上傳圖片後直接進行預覽,而不用先經過後臺。
var input = document.getElementById("file"); //input file
input.onchange = function(){
var file = this.files[0];
if(!!file){
var reader = new FileReader();
// 將圖片轉成DataURL格式
reader.readAsDataURL(file);
reader.onload = function(){
//讀取完畢後輸出結果
document.getElementById("file_img").src = reader.result //顯示上傳的圖片
console.log(reader.result);
}
}
}
URL
URL.createObjectURL(blob)
//blob參數是一個File對象或者Blob對象.
var objecturl = window.URL.createObjectURL(blob);
上面的代碼會對二進制數據生成一個 URL
,這個 URL
可以放置於任何通常可以放置 URL
的地方,比如 img
標籤的 src
屬性。需要注意的是,即使是同樣的二進制數據,每調用一次 URL.createObjectURL
方法,就會得到一個不一樣的 URL
。
這個 URL 的存在時間,等同於網頁的存在時間,一旦網頁刷新或卸載,這個 URL 就失效。(File 和 Blob 又何嘗不是這樣呢)除此之外,也可以手動調用 URL.revokeObjectURL
方法,使 URL 失效。
URL.revokeObjectURL(objectURL);
當不再需要這些 URL 對象時,每個對象必須通過調用 URL.revokeObjectURL()
方法來釋放。瀏覽器會在文檔退出的時候自動釋放它們,但是爲了獲得最佳性能和內存使用狀況,你應該在安全的時機主動釋放掉它們。
實際應用
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文件上傳</title>
<script src="./lib/jquery.js"></script>
<style type="text/css">
#file{
display: block;
width: 400px;
height: 300px;
opacity:0;
margin: -300px 0 0 0;
}
#preview{
display: block;
width: 400px;
height: 300px;
}
</style>
</head>
<body>
<img id="preview" src="" alt="點擊上傳圖片"/>
<input type="file" id="file" />
</body>
</html>
<script type="text/javascript">
$('#file').on('change', function(){
//獲取文件列表對象
var fileList = $('#file')[0].files;
//創建文件流獲取文件地址
var src = window.URL.createObjectURL(fileList[0]);
//設置圖片路徑
$("#preview").attr("src", src);
$("#preview").load(function() {
window.URL.revokeObjectURL(src);
});
});
</script>