在瀏覽器中操做文件,多數狀況下用到的是 File
對象,從 <input type='file' />
元素獲取,進而繼續操做(例如將選擇的圖片展現在頁面上,用ajax將文件上傳至服務器等)。這裏介紹在瀏覽器中操做文件的相關API.javascript
File
對象繼承自 Blob
對象,先看看 Blob
對象。html
Blob
對象表示一個不可變、原始數據的類文件對象。Blob 表示的不必定是JavaScript原生格式的數據。java
MIME
類型。示例:web
var content1 = ['This is my firt trip to an island'];
var blob1 = new Blob(content, {type: 'text/plain'});
var content2 = {name: 'Alice', age: 23};
var blob2 = new Blob([JSON.stringify(content2, null, 2)], {type: 'application/json'});
複製代碼
屬性名稱 | 讀/寫 | 描述 |
---|---|---|
size | 只讀 | Blob 對象中所包含數據的大小(字節)。 |
type | 只讀 | 一個字符串,代表該Blob對象所包含數據的MIME 類型。若是類型未知,則該值爲空字符串。例如 "image/png". |
示例:ajax
var content = ['<div id="box"><p class="pra">a paragraph</p></div>'];
var blob = new Blob(content, {type: 'text/html'});
console.log(blob.size); // 50
console.log(blob.type); // text/html
複製代碼
slice
方法接收三個可選參數,start
和 end
都是數值,表示截取的範圍,contentType
指定截取的內容的 MIME
類型。返回一個新的 Blob
對象。json
var blob = new Blob(['This is an example of Blob slice method'], {type: 'text/plain'});
console.log(blob.size); // 39
var newBlob = blob.slice(10, 20, 'text/plain');
console.log(newBlob.size); // 10
複製代碼
從 Blob
對象中讀取內容可使用 FileReader
. 下文會介紹。canvas
咱們接觸的多數關於 File
的操做都是讀取,js也爲咱們提供了手動建立 File
對象的構造函數:File(bits, name[, options])
。數組
bits (required) ArrayBuffer,ArrayBufferView,Blob,或者 Array[string] — 或者任何這些對象的組合。這是 UTF-8 編碼的文件內容。。瀏覽器
name [String] (required) 文件名稱,或者文件路徑.安全
options [Object] (optional) 選項對象,包含文件的可選屬性。可用的選項以下:
type
: string, 表示將要放到文件中的內容的MIME
類型。默認值爲 '' 。lastModified
: 數值,表示文件最後修改時間的 Unix 時間戳(毫秒)。默認值爲 Date.now()。示例:
var file1 = new File(['text1', 'text2'], 'test.txt', {type: 'text/plain'});
複製代碼
根據已有的 blob
對象建立 File
對象:
var file2 = new File([blob], 'test.png', {type: 'image/png'});
複製代碼
File
對象的實例內容不可見,可是有如下屬性能夠訪問:
屬性名稱 | 讀/寫 | 描述 |
---|---|---|
name | 只讀 | 返回文件的名稱.因爲安全緣由,返回的值並不包含文件路徑 。 |
type | 只讀 | 返回 File 對象所表示文件的媒體類型(MIME)。例如 PNG 圖像是 "image/png". |
lastModified | 只讀 | number, 返回所引用文件最後修改日期,自 1970年1月1日0:00 以來的毫秒數。 |
lastModifiedDate | 只讀 | Date, 返回當前文件的最後修改日期,若是沒法獲取到文件的最後修改日期,則使用當前日期來替代。 |
示例:
<input type="file" id='file'>
複製代碼
document.getElementById('file').addEventListener('change', function(event){
const file = this.files[0];
if (file) {
console.log(file.name);
console.log(file.size);
console.log(file.lastModified);
console.log(file.lastModifiedDate);
}
});
複製代碼
備註: 基於當前的實現,瀏覽器不會實際讀取文件的字節流,來判斷它的媒體類型。它基於文件擴展來假設;將PNG 圖像文件的後綴名重命名爲 .txt
,那麼讀取的該文件的 type
屬性值爲 "text/plain", 而不是 "image/png" 。並且,file.type
僅僅對常見文件類型可靠。例如圖像、文檔、音頻和視頻。不常見的文件擴展名會返回空字符串。開發者最好不要依靠這個屬性,做爲惟一的驗證方案。
File
對象沒有定義額外的方法,因爲繼承了 Blob
對象,也就繼承了 slice
方法,用法同上文 Blob
的 slice
方法。
FileReader, URL.createObjectURL(), createImageBitmap(), 及 XMLHttpRequest.send() 都能處理 Blob 和 File。
FileReader
對象容許Web應用程序異步讀取存儲在用戶計算機上的文件(或原始數據緩衝區)的內容,使用File
或Blob
對象指定要讀取的文件或數據。
其中 File
對象能夠是來自用戶在一個 <input>
元素上選擇文件後返回的 FileList
, 也能夠來自拖放操做生成的 DataTransfer
對象,還能夠是來自在一個 HTMLCanvasElement
上執行 mozGetAsFile()
方法後返回結果。
var reader = new FileReader()
構造函數不須要傳入參數,返回一個 FileReader
的實例。FileReader
繼承 EventTarget
對象。
屬性名稱 | 讀/寫 | 描述 |
---|---|---|
error | 只讀 | DOMException 的實例,表示在讀取文件時發生的錯誤 。 |
result | 只讀 | 文件的內容,該屬性僅在讀取操做完成後(load)後纔有效,格式取決於讀取方法 |
readyState | 只讀 | 表示讀取文件時狀態的數字 |
備註: readeyState
的取值以下:
值 | 常量名 | 描述 |
---|---|---|
0 | EMPTY | 尚未加載任何數據 |
1 | LOADING | 數據正在被加載 |
2 | DONE | 已完成所有的讀取請求. |
使用示例:
var reader = new FileReader();
console.log(reader.error); // null
console.log(reader.result); // null
console.log(reader.readyState); // 0
console.log(reader.EMPTY); // 0
console.log(reader.LOADING); // 1
console.log(reader.DONE); // 2
複製代碼
EMPTY
、LOADING
、DONE
這三個屬性同時存在於 FileReader
和它的的原型對象上,所以實例上有這三個屬性,FileReader
對象自己也有這三個屬性:
console.log(FileReader.EMPTY); // 0
console.log(FileReader.LOADING); // 1
console.log(FileReader.DONE); // 2
複製代碼
文件的讀取是一個異步的過程,和 XMLHttpRequest
對象同樣,在讀取操做過程當中會觸發一系列事件。
事件名稱 | 描述 | 使用示例 |
---|---|---|
abort | 讀取操做被中斷時觸發。 | reader.onabort = function(event) {} |
error | 在讀取操做發生錯誤時觸發。 | reader.onerror = function(event) {} |
load | 讀取操做完成時觸發。 | reader.addEventListener('load', function(event) {}) |
loadstart | 讀取操做開始時觸發。 | reader.onloadstart = function(event) {} |
loadend | 讀取操做結束時(要麼成功,要麼失敗)觸發。 | reader.onloadend = function(event) {} |
progress | 在讀取Blob時觸發。 | reader.onprogress = function(event) {} |
FileReader
的實例具備如下可操做的方法:
方法名稱 | 描述 | 使用示例 |
---|---|---|
abort() | 手動終止讀取操做,只有當 readyState 爲 1 時才能調用,調用後,readyState 值爲 2 |
reader.abort() |
readAsArrayBuffer(blob) | 讀取指定的 Blob 或 File 對象。讀取操做完成後(觸發loadend 事件),result 屬性將包含一個 ArrayBuffer 對象表示所讀取的文件的數據。 |
reader.readAsArrayBuffer(blob) |
readAsDataURL(blob) | 讀取指定的 Blob 或 File 對象。讀取操做完成後(觸發loadend 事件),result 屬性將包含一個 data:URL 格式的字符串(base64編碼) |
reader.readAsArrayBuffer(file) |
readAsBinaryString(blob) | 已廢棄,用 readAsArrayBuffer 代替 |
-- |
readAsText(blob[, encoding]) | 將 Blob 或者 File 對象轉根據特殊的編碼格式轉化爲內容(字符串形式), 默認編碼是 utf-8 |
reader.readAsArrayBuffer(blob) |
讀取本地圖片示例:
<input type="file" id='file' accept="image/png, image/jpg, image/jpeg, image/gif" />><br />>
<img src="" alt="Image preview...">
複製代碼
var preview = document.querySelector('img');
var reader = new FileReader();
reader.addEventListener("load", function () {
preview.src = reader.result;
}, false);
document.getElementById('file').addEventListener('change', function (event) {
var file = this.files[0];
if (file) {
reader.readAsDataURL(file);
}
});
複製代碼
dataURL是base64
編碼的數據格式,展現類型爲字符串,形如: data:image/jpeg;base64,/9j/4QXERXhpZgAATU...
將 dataURL
轉爲 blob
對象:
function dataURLToBlob (dataurl) {
let arr = dataurl.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
複製代碼
結合上例,根據已有的 <img>
對象建立一個 File
對象:
reader.addEventListener("load", function () {
preview.src = reader.result;
var blob = dataURLToBlob(reader.result);
var newFile = new File([blob], 'test.jpeg', {type: blob.type});
console.log(newFile.name); // test.jpeg
console.log(newFile.type);
console.log(newFile.size);
}, false);
複製代碼
將圖片文件轉換成 data:URL
格式供 <img>
元素展現,除了使用 fileReader.readAsDataURL
外,還可使用 URL.createObjectURL
方法。 URL.createObjectURL(blob)
方法返回一個 blob:
開頭的字符串,指向文件在內存中的地址。
<input type="file" id='file' accept="image/png, image/jpg, image/jpeg, image/gif" /><br />
<img src="" alt="Image preview...">
複製代碼
var preview = document.querySelector('img');
document.getElementById('file').addEventListener('change', function (event) {
var file = this.files[0];
if (file) {
preview.src = URL.createObjectURL(file);
}
});
複製代碼
綜合以上,能夠實現一個簡單的粘貼圖片並顯示的功能。HTML5提供的內容編輯功能,能夠粘貼部分圖片,例如從網頁上覆制的圖片。可是使用截圖工具截取的圖片沒法粘貼顯示,並且從網頁上覆制的圖片會帶有原來的樣式,其圖片url也是原來圖片的指向。咱們使用如下代碼能夠統一這兩種粘貼操做,實現統一的效果。
<div id="comment" contenteditable></div>
複製代碼
#comment{
border: 1px solid #ccc;
min-height: 500px;
padding: 10px;
}
#comment:focus {
border-color: #ccc;
outline: none;
}
.img-paste {
max-width: 100%;
}
複製代碼
var comment = document.getElementById('comment');
comment.addEventListener('paste', function(event) {
console.log(event);
var item = event.clipboardData.files[0];
if (item && /image/.test(item.type)) {
var img = new Image();
img.src = URL.createObjectURL(item);
img.className = 'img-paste';
this.appendChild(img);
event.preventDefault();
}
}, false);
複製代碼
實例效果能夠查看這裏。