JS前端使用Blob和File讀取文件的操作代碼
歷史上,JavaScript
無(wú)法處理二進(jìn)制數(shù)據(jù)。如果一定要處理的話,只能使用 charCodeAt()
方法,一個(gè)個(gè)字節(jié)地從文字編碼轉(zhuǎn)成二進(jìn)制數(shù)據(jù),還有一種辦法是將二進(jìn)制數(shù)據(jù)轉(zhuǎn)成 Base64
編碼,再進(jìn)行處理。這兩種方法不僅速度慢,而且容易出錯(cuò)。ECMAScript 5
引入了 Blob
對(duì)象,允許直接操作二進(jìn)制數(shù)據(jù)。
Blob
對(duì)象是一個(gè)代表二進(jìn)制數(shù)據(jù)的基本對(duì)象,在它的基礎(chǔ)上,又衍生出一系列相關(guān)的API,用來(lái)操作文件。
File
對(duì)象:負(fù)責(zé)處理那些以文件形式存在的二進(jìn)制數(shù)據(jù),也就是操作本地文件;FileList
對(duì)象:File
對(duì)象的網(wǎng)頁(yè)表單接口;FileReader
對(duì)象:負(fù)責(zé)將二進(jìn)制數(shù)據(jù)讀入內(nèi)存內(nèi)容;URL
對(duì)象:用于對(duì)二進(jìn)制數(shù)據(jù)生成URL
Blob
Blob
(Binary Large Object) 對(duì)象代表了一段二進(jìn)制數(shù)據(jù),提供了一系列操作接口。其他操作二進(jìn)制數(shù)據(jù)的API(比如 File
對(duì)象),都是建立在 Blob
對(duì)象基礎(chǔ)上的,繼承了它的屬性和方法。
創(chuàng)建 Blob 類型的對(duì)象
生成 Blob
對(duì)象有兩種方法:一種是使用 Blob
構(gòu)造函數(shù),另一種是對(duì)現(xiàn)有的 Blob
對(duì)象使用 slice
方法切出一部分。
1. new Blob()
Blob
構(gòu)造函數(shù),接受兩個(gè)參數(shù)。第一個(gè)參數(shù)是一個(gè)包含實(shí)際數(shù)據(jù)的數(shù)組,這個(gè)數(shù)組中的元素可以為 DOMString
,或者 ArrayBuffer
,第二個(gè)參數(shù)是數(shù)據(jù)的類型,這兩個(gè)參數(shù)都不是必需的。
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()
此方法返回一個(gè)新的 Blob
對(duì)象,包含了原 Blob
對(duì)象中指定范圍內(nèi)的數(shù)據(jù)
Blob.slice(start:number, end:number, contentType:string)。start:開(kāi)始索引,默認(rèn)為0;end:截取結(jié)束索引(不包括end);contentType:新Blob的MIME類型,默認(rèn)為空字符串
Blob 對(duì)象的屬性
- Blob.size:
Blob
對(duì)象中所包含數(shù)據(jù)的大小(字節(jié))。該屬性為只讀; - Blob.type: 一個(gè)字符串,表明該
Blob
對(duì)象所包含數(shù)據(jù)的MIME
類型。如果類型未知,則該值為空字符串。該屬性為只讀
Blob 應(yīng)用實(shí)例
下面是一個(gè)使用XMLHttpRequest對(duì)象,將大文件分割上傳的例子。
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
接口提供有關(guān)文件的信息,并允許網(wǎng)頁(yè)中的JavaScript
訪問(wèn)其內(nèi)容。
File
對(duì)象可以用來(lái)獲取某個(gè)文件的信息,還可以用來(lái)讀取這個(gè)文件的內(nèi)容。通常情況下, File
對(duì)象是來(lái)自用戶在一個(gè) <input>
元素上選擇文件后返回的 FileList
對(duì)象,也可以是來(lái)自由拖放操作生成的 DataTransfer
對(duì)象。
用戶在選擇一個(gè)或者多個(gè)文件后,可以通過(guò) File
API訪問(wèn)這些File
對(duì)象,這些對(duì)象被包含在一個(gè) FileList
對(duì)象中。所有 type
為 file
的 input
都有一個(gè) files
屬性,通過(guò) Element.files
可以返回 FileList
對(duì)象。
<body> <input type="file" id="fileInput" name="file" multiple="multiple" accept="image/*"> <script> var fileInput = document.querySelector("#fileInput"); fileInput.addEventListener("change", function (event) { // 文件列表對(duì)象 var fileList = this.files; // 獲取第一個(gè)文件 var file = fileInput.files[0]; // 文件名 var filename = file.name; // 文件大小 var filesize = file.size; //文件的 MIME 類型,如果分辨不出類型,則為空字符串,該屬性只讀 var type = file.type; // 文件的上次修改時(shí)間,格式為時(shí)間戳 var lastModified = file.lastModified; // 文件的上次修改時(shí)間,格式為 Date 對(duì)象實(shí)例 var lastModifiedDate = file.lastModifiedDate; }, false); console.log(fileList); // 上傳了兩個(gè)文件,F(xiàn)ileList {0: File, 1: File, length: 2} </script> </body>
File 對(duì)象的屬性:
- name:文件名,該屬性只讀。
- size:文件大小,單位為字節(jié),該屬性只讀。
- type:文件的 MIME 類型,如果分辨不出類型,則為空字符串,該屬性只讀。
- lastModified:文件的上次修改時(shí)間,格式為時(shí)間戳。
- lastModifiedDate:文件的上次修改時(shí)間,格式為 Date 對(duì)象實(shí)例
File 對(duì)象的方法:
File 接口沒(méi)有定義任何方法,但是它從 Blob 接口繼承了以下方法:
Blob.slice([start[, end[, contentType]]])
返回一個(gè)新的 Blob
對(duì)象,它包含有源 Blob
對(duì)象中指定范圍內(nèi)的數(shù)據(jù)。
FileReader
我們知道 Blob
對(duì)象只是二進(jìn)制數(shù)據(jù)的容器,本身并不能操作二進(jìn)制,FileReader
對(duì)象就是專門操作二進(jìn)制數(shù)據(jù)的,FileReader
主要用于將文件內(nèi)容讀入內(nèi)存,通過(guò)一系列異步接口,可以在主線程中訪問(wèn)本地文件。
構(gòu)造函數(shù)
var reader = new FileReader();
屬性
- FileReader.error:表示在讀取文件時(shí)發(fā)生的錯(cuò)誤;
- FileReader.readyState:0-還沒(méi)有加載任何數(shù)據(jù), 1-數(shù)據(jù)正在被加載, 2-已完成全部的讀取請(qǐng)求;
- FileReader.result:文件的內(nèi)容。該屬性僅在讀取操作完成后才有效,數(shù)據(jù)的格式取決于使用哪個(gè)方法來(lái)啟動(dòng)讀取操作。
事件
- FileReader.onabort:處理 abort 事件。該事件在讀取操作被中斷時(shí)觸發(fā);
- FileReader.onerror:處理 error 事件。該事件在讀取操作發(fā)生錯(cuò)誤時(shí)觸發(fā);
- FileReader.onload:處理 load 事件。該事件在讀取操作完成時(shí)觸發(fā);
- FileReader.onloadstart:處理 loadstart 事件。該事件在讀取操作開(kāi)始時(shí)觸發(fā);
- FileReader.onloadend:處理 loadend 事件。該事件在讀取操作結(jié)束時(shí)(要么成功,要么失?。┯|發(fā);
- FileReader.onprogress:處理 progress 事件。該事件在讀取 Blob 時(shí)觸發(fā)
方法
- FileReader.abort():中止讀取操作。在返回時(shí),readyState 屬性為DONE;
- FileReader.readAsArrayBuffer():開(kāi)始讀取指定的 Blob 中的內(nèi)容, 一旦完成, result 屬性中保存的將是被讀取文件的 ArrayBuffer 數(shù)據(jù)對(duì)象;
- FileReader.readAsBinaryString():開(kāi)始讀取指定的 Blob 中的內(nèi)容。一旦完成,result 屬性中將包含所讀取文件的原始二進(jìn)制數(shù)據(jù), 該方法將文件讀取為二進(jìn)制字符串,通常我們將它傳送到后端,后端可以通過(guò)這段字符串存儲(chǔ)文件;
- FileReader.readAsDataURL():開(kāi)始讀取指定的 Blob 中的內(nèi)容。一旦完成,result 屬性中將包含一個(gè) data: URL 格式的字符串以表示所讀取文件的內(nèi)容;
- FileReader.readAsText():開(kāi)始讀取指定的 Blob 中的內(nèi)容。一旦完成,result 屬性中將包含一個(gè)字符串以表示所讀取的文件內(nèi)容, 該方法有兩個(gè)參數(shù),其中第二個(gè)參數(shù)是文本的編碼方式,默認(rèn)值為 UTF-8。這個(gè)方法非常容易理解,將文件以文本方式讀取,讀取的結(jié)果即是這個(gè)文本文件中的內(nèi)容。
實(shí)際應(yīng)用
上傳圖片后直接進(jìn)行預(yù)覽,而不用先經(jīng)過(guò)后臺(tái)。
var input = document.getElementById("file"); //input file input.onchange = function(){ var file = this.files[0]; if(!!file){ var reader = new FileReader(); // 將圖片轉(zhuǎn)成DataURL格式 reader.readAsDataURL(file); reader.onload = function(){ //讀取完畢后輸出結(jié)果 document.getElementById("file_img").src = reader.result //顯示上傳的圖片 console.log(reader.result); } } }
URL
URL.createObjectURL(blob)
//blob參數(shù)是一個(gè)File對(duì)象或者Blob對(duì)象. var objecturl = window.URL.createObjectURL(blob);
上面的代碼會(huì)對(duì)二進(jìn)制數(shù)據(jù)生成一個(gè) URL
,這個(gè) URL
可以放置于任何通??梢苑胖?URL
的地方,比如 img
標(biāo)簽的 src
屬性。需要注意的是,即使是同樣的二進(jìn)制數(shù)據(jù),每調(diào)用一次 URL.createObjectURL
方法,就會(huì)得到一個(gè)不一樣的 URL
。
這個(gè) URL 的存在時(shí)間,等同于網(wǎng)頁(yè)的存在時(shí)間,一旦網(wǎng)頁(yè)刷新或卸載,這個(gè) URL 就失效。(File 和 Blob 又何嘗不是這樣呢)除此之外,也可以手動(dòng)調(diào)用 URL.revokeObjectURL
方法,使 URL 失效。
URL.revokeObjectURL(objectURL);
當(dāng)不再需要這些 URL 對(duì)象時(shí),每個(gè)對(duì)象必須通過(guò)調(diào)用 URL.revokeObjectURL()
方法來(lái)釋放。瀏覽器會(huì)在文檔退出的時(shí)候自動(dòng)釋放它們,但是為了獲得最佳性能和內(nèi)存使用狀況,你應(yīng)該在安全的時(shí)機(jī)主動(dòng)釋放掉它們。
實(shí)際應(yīng)用
<!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="點(diǎn)擊上傳圖片"/> <input type="file" id="file" /> </body> </html> <script type="text/javascript"> $('#file').on('change', function(){ //獲取文件列表對(duì)象 var fileList = $('#file')[0].files; //創(chuàng)建文件流獲取文件地址 var src = window.URL.createObjectURL(fileList[0]); //設(shè)置圖片路徑 $("#preview").attr("src", src); $("#preview").load(function() { window.URL.revokeObjectURL(src); }); }); </script>
參考資料
到此這篇關(guān)于JS前端使用Blob和File讀取文件的文章就介紹到這了,更多相關(guān)js使用Blob和File讀取文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript中常見(jiàn)的獲取當(dāng)前日期方法
在我們開(kāi)發(fā)的許多應(yīng)用程序都會(huì)用到某種日期功能,無(wú)論是內(nèi)容的創(chuàng)建日期還是活動(dòng)的時(shí)間戳等等,這篇文章主要給大家介紹了關(guān)于JavaScript中常見(jiàn)的獲取當(dāng)前日期方法,需要的朋友可以參考下2024-06-06js動(dòng)態(tài)添加刪除,后臺(tái)取數(shù)據(jù)(示例代碼)
這篇文章主要是對(duì)js動(dòng)態(tài)添加刪除,后臺(tái)取數(shù)據(jù)(示例代碼)進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-11-11js如何獲取當(dāng)前網(wǎng)站的協(xié)議、域名、端口號(hào)
文章介紹了如何使用JavaScript的window.location對(duì)象獲取當(dāng)前網(wǎng)站的協(xié)議、域名、端口號(hào),并提供了示例代碼,此外,還介紹了如何將這些部分組合成一個(gè)完整的URL2025-01-01javascript實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇游戲
本文很簡(jiǎn)單,給大家分享了一段使用javascript實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇游戲的代碼,算是對(duì)自己學(xué)習(xí)javascript的一次小小的總結(jié),代碼參考了網(wǎng)友的部分內(nèi)容,推薦給大家,希望對(duì)大家能夠有所幫助。2015-03-03KnockoutJS 3.X API 第四章之?dāng)?shù)據(jù)控制流with綁定
這篇文章主要介紹了KnockoutJS 3.X API 第四章之?dāng)?shù)據(jù)控制流with綁定的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10es6中的import導(dǎo)入模塊 和 export導(dǎo)出模塊詳解
require 是 CommonJS 模塊系統(tǒng)中用于導(dǎo)入模塊的關(guān)鍵字,采用同步加載方式;而 import 和 export 是 ES6 模塊系統(tǒng)中用于導(dǎo)入和導(dǎo)出模塊的關(guān)鍵字,采用靜態(tài)加載方式,并且支持異步加載,這篇文章主要介紹了es6中的import導(dǎo)入模塊 和 export導(dǎo)出模塊,需要的朋友可以參考下2023-11-11