JavaScript 文件對象詳解

在瀏覽器中操做文件,多數狀況下用到的是 File 對象,從 <input type='file' /> 元素獲取,進而繼續操做(例如將選擇的圖片展現在頁面上,用ajax將文件上傳至服務器等)。這裏介紹在瀏覽器中操做文件的相關API.javascript

File 對象繼承自 Blob 對象,先看看 Blob 對象。html

1. Blob 對象

Blob 對象表示一個不可變、原始數據的類文件對象。Blob 表示的不必定是JavaScript原生格式的數據。java

Blob構造函數 Blob(array[, options])

  • array 是一個由ArrayBuffer, ArrayBufferView, Blob, string 等對象構成的 Array ,或者其餘相似對象的混合體,它將會被放進 Blob。string會被編碼爲UTF-8。
  • options 是一個可選的對象,它可能會指定以下兩個屬性:
    • type,默認值爲 "",它表明了將會被放入到blob中的數組內容的MIME類型
    • endings,默認值爲"transparent",用於指定包含行結束符\n的字符串如何被寫入。 它是如下兩個值中的一個: "native",表明行結束符會被更改成適合宿主操做系統文件系統的換行符,或者 "transparent",表明會保持blob中保存的結束符不變。

示例: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'});
複製代碼

Blob實例屬性

屬性名稱 讀/寫 描述
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
複製代碼

Blob實例方法

  • slice([start[, end[, contentType]]])

slice 方法接收三個可選參數,startend 都是數值,表示截取的範圍,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

2. File 對象

File構造函數

咱們接觸的多數關於 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實例屬性

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實例方法

  • slice([start[, end[, contentType]]])

File 對象沒有定義額外的方法,因爲繼承了 Blob 對象,也就繼承了 slice方法,用法同上文 Blobslice 方法。

FileReader, URL.createObjectURL(), createImageBitmap(), 及 XMLHttpRequest.send() 都能處理 Blob 和 File。

3. FileReader 對象

FileReader 對象容許Web應用程序異步讀取存儲在用戶計算機上的文件(或原始數據緩衝區)的內容,使用 FileBlob 對象指定要讀取的文件或數據。

其中 File 對象能夠是來自用戶在一個 <input> 元素上選擇文件後返回的 FileList, 也能夠來自拖放操做生成的 DataTransfer 對象,還能夠是來自在一個 HTMLCanvasElement 上執行 mozGetAsFile() 方法後返回結果。

FileReader構造函數

var reader = new FileReader()

構造函數不須要傳入參數,返回一個 FileReader 的實例。FileReader 繼承 EventTarget對象。

FileReader實例屬性

屬性名稱 讀/寫 描述
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
複製代碼

EMPTYLOADINGDONE 這三個屬性同時存在於 FileReader 和它的的原型對象上,所以實例上有這三個屬性,FileReader 對象自己也有這三個屬性:

console.log(FileReader.EMPTY);   // 0
console.log(FileReader.LOADING); // 1
console.log(FileReader.DONE);    // 2
複製代碼

FileReader事件

文件的讀取是一個異步的過程,和 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實例方法

FileReader 的實例具備如下可操做的方法:

方法名稱 描述 使用示例
abort() 手動終止讀取操做,只有當 readyState 爲 1 時才能調用,調用後,readyState 值爲 2 reader.abort()
readAsArrayBuffer(blob) 讀取指定的 BlobFile 對象。讀取操做完成後(觸發loadend事件),result屬性將包含一個 ArrayBuffer 對象表示所讀取的文件的數據。 reader.readAsArrayBuffer(blob)
readAsDataURL(blob) 讀取指定的 BlobFile 對象。讀取操做完成後(觸發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);
  }
});
複製代碼

讀取多個文件示例 - CodePen

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);
複製代碼

URL.createObjectURL

將圖片文件轉換成 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);
複製代碼

實例效果能夠查看這裏

參考連接

相關文章
相關標籤/搜索