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 類(lèi)型的對(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ù)的類(lèi)型,這兩個(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類(lèi)型,默認(rèn)為空字符串
Blob 對(duì)象的屬性
- Blob.size:
Blob
對(duì)象中所包含數(shù)據(jù)的大?。ㄗ止?jié))。該屬性為只讀; - Blob.type: 一個(gè)字符串,表明該
Blob
對(duì)象所包含數(shù)據(jù)的MIME
類(lèi)型。如果類(lèi)型未知,則該值為空字符串。該屬性為只讀
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)自用戶(hù)在一個(gè) <input>
元素上選擇文件后返回的 FileList
對(duì)象,也可以是來(lái)自由拖放操作生成的 DataTransfer
對(duì)象。
用戶(hù)在選擇一個(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 類(lèi)型,如果分辨不出類(lèi)型,則為空字符串,該屬性只讀 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 類(lèi)型,如果分辨不出類(lèi)型,則為空字符串,該屬性只讀。
- 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ì)象就是專(zhuān)門(mén)操作二進(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)容。該屬性?xún)H在讀取操作完成后才有效,數(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)文章
js實(shí)現(xiàn)小球在頁(yè)面規(guī)定的區(qū)域運(yùn)動(dòng)
這篇文章主要為大家詳細(xì)介紹了js控制小球在規(guī)定范圍運(yùn)動(dòng),碰到邊界就改變運(yùn)動(dòng)方向,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06js實(shí)現(xiàn)簡(jiǎn)單頁(yè)面全屏
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)簡(jiǎn)單頁(yè)面全屏的功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09javascript實(shí)現(xiàn)數(shù)獨(dú)解法
數(shù)獨(dú)(すうどく,Sūdoku)是一種運(yùn)用紙、筆進(jìn)行演算的邏輯游戲。玩家需要根據(jù)9×9盤(pán)面上的已知數(shù)字,推理出所有剩余空格的數(shù)字,并滿(mǎn)足每一行、每一列、每一個(gè)粗線宮內(nèi)的數(shù)字均含1-9,不重復(fù)。2015-03-03微信小程序嵌入H5頁(yè)面(web-view)的方法詳解
使用<web-view>標(biāo)簽?zāi)茉谛〕绦蛑写蜷_(kāi)外部網(wǎng)頁(yè),但是要打開(kāi)的網(wǎng)頁(yè)的域名必須跟小程序的業(yè)務(wù)域名(業(yè)務(wù)域名可以在小程序的后臺(tái)管理界面添加)一致,否則在真機(jī)上是打不開(kāi)的,下面這篇文章主要給大家介紹了關(guān)于微信小程序嵌入H5頁(yè)面(web-view)的相關(guān)資料,需要的朋友可以參考下2022-09-09JavaScript setTimeout與setTimeinterval使用案例詳解
這篇文章主要介紹了JavaScript setTimeout與setTimeinterval使用案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08javascript動(dòng)態(tài)分頁(yè)的實(shí)現(xiàn)方法實(shí)例
最近的項(xiàng)目需要添加一個(gè)分頁(yè)導(dǎo)航的功能,沒(méi)有用網(wǎng)上封裝好的文件,通過(guò)JS自己簡(jiǎn)單實(shí)現(xiàn)了效果,這篇文章主要給大家介紹了關(guān)于javascript動(dòng)態(tài)分頁(yè)的實(shí)現(xiàn)方法,需要的朋友可以參考下2022-06-06JavaScript Tips 使用DocumentFragment加快DOM渲染速度
大家在開(kāi)發(fā)JavaScript應(yīng)用的時(shí)候,如果遇到這種大量節(jié)點(diǎn)的情況,不妨將DocumentFragment作為一個(gè)備選的方案。2010-06-06QQ強(qiáng)制聊天功能代碼(加強(qiáng)版,兼容QQ2010)
QQ強(qiáng)制聊天功能代碼,腳本之家以前也發(fā)布過(guò),但已經(jīng)不能用了,這個(gè)是新版本,經(jīng)過(guò)測(cè)試,完全兼容新版本的qq.2010-06-06原生js實(shí)現(xiàn)彈窗消息動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了原生js實(shí)現(xiàn)彈窗消息動(dòng)畫(huà),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11