徹底理解responseType中blob和arrayBuffer


一般的xhr請求

 let url = window.URL || window.webkitURL;

let xhr = new XMLHttpRequest();

xhr.open(method, url, [,async=true,]);

xhr.ontimeout = ()=>{};

xhr.onreadystatechange ()=>{

if(xhr.readystate === 4) {

if(xhr.status =200) {

let res = xhr.responseText;

let blob = new Blob([res], {type: 'video/mpeg4'});

videoEle.src = url.createObjectURL(blob);

};

}

};

 上面代碼處理一般的xhr請求足夠滿足,即返回類型為DOMString的,但是處理視頻下載並且存儲后播放就會有問題,上面代碼處理異步視頻下載有兩個bug,如果你都知道,就不需要往下看了^_^

再次認識responseType

responseType值的類型可為如下

數據類型
’ ‘ DOMString (這個是默認類型)
arraybuffer ArrayBuffer對象
blob Blob對象
document Document對象
json JavaScript object, parsed from a JSON string returned by the server
text DOMString

video后台為設置的content-type為application/octet-stream,表示二進制流。。當時就被這貨坑了一下,以為返回的數據能夠夠Blob構造函數接收,並正確顯示。

 

Blob對象

 

Blob也是比較有意思,mdn上的解釋是Blob對象表示不可變的類似文件對象的原始數據。Blob表示不一定是JavaScript原生形式的數據。

^_^其實就是英文Binary large Object,mysql有此類型數據結構

let blog = new Blob(arrya, options);
 
 
 
         
  • 1

Blob() 構造函數返回一個新的 Blob 對象。

  • array 是一個由ArrayBuffer, ArrayBufferView, Blob, DOMString 等對象構成的 Array ,或者其他類似對象的混合體,它將會被放進 Blob。DOMStrings會被編碼為UTF-8。

  • options 是一個可選的BlobPropertyBag字典,它可能會指定如下兩個屬性:

    type,默認值為 “”,它代表了將會被放入到blob中的數組內容的MIME類型。


ArrayBuffer涉及面比較廣,我的理解是ArrayBuffer代表內存之中的一段二進制數據,一旦生成不能再改。可以通過視圖(TypedArray和DataView)進行操作。

TypedArray數組只是一層視圖,本身不儲存數據,它的數據都儲存在底層的ArrayBuffer對象之中, 所以通過同一個arraybuffer生成的TypedArray共享內存數據。

nodejs中的buffer是對Uint8Array的實現。詳細可參考另外一篇我寫的文章


正確的video流打開方式

還有一點xhr.responseText的類型為DOMString,只有當responseType為DOMString時才有正確數據,其他類型獲取響應實體用xhr.response。因為一般我們都是獲取json字符串,此處也需要注意下。 
so正確的代碼如下:

let url = window.URL || window.webkitURL;     let xhr = new XMLHttpRequest();     xhr.open(method, url, [,async=true,]);     xhr.responseType = 'blob' ; //arraybuffer也可以     xhr.ontimeout = ()=>{};     xhr.onreadystatechange=()=>{       if(xhr.readystate === 4) {         if(xhr.status =200) {             let res = xhr.response;  //不是responseText。           /*           *最近看別人的代碼,發現可以這么寫           * let res = 'response' in xhr ? xhr.response : xhr.responseText           * 厲害!!!           */           let blob = new Blob([res], {type: 'video/mpeg4'});           ....           ....           videoEle.src = url.createObjectURL(blob);           //Videos on Android do not play when the src is set as a blob via create URL, 在移動端有兼容問題         };       }     };
 
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

后面的內容與本文無關,純作記錄。

后續

項目中的video都存儲在移動設備中,如果都放在blob中,會造成內存的大量占用,因是cordova的webapp形式,故采用插件cordova-plugin-file, 
相關寫文件代碼如下

function writeSystemFile(videoBlob, isAppend) {     let self = this;     window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {       //console.log('openFsObj', fs);       //console.log('open file name: ', fs.name);       fs.root.getFile(self._storeVideoName, { create: true, exclusive: false },function (fileEntry) {         // var dataObj = new Blob([videoData], { type: 'text/plain' });         self.writeFile(fileEntry, videoBlob, isAppend);       }, function(e) {         console.log('onErrorCreateFile, error:', e);       });     }, function(e) {       console.log('onErrorLoadFs, error:', e);     });   }    function writeFile(fileEntry, dataObj, isAppend) {     // let self = this;     fileEntry.createWriter(function (fileWriter) {       fileWriter.onwriteend = function() {         console.log('Successful file write...');         //console.log('fileWriterEnd.length:', fileWriter.length);       };       fileWriter.onerror = function (e) {         console.log('Failed file write: ' + e.toString());       };       if(isAppend) { //表示是否追加文件         try {           console.log('fileWriter.length:', fileWriter.length);           fileWriter.seek(fileWriter.length);         } catch(e) {           console.log('file doesn`t exist:', e.toString());         }       }       //console.log('fileWriterStart.length:', fileWriter.length);       fileWriter.write(dataObj);      });   }
 
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

讀文件代碼

function readSystemFile() {     let self = this;     console.log('readSystemFile self._storeVideoName:', self._storeVideoName);     window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {       fs.root.getFile(self._storeVideoName, { create: true, exclusive: false },function (fileEntry) {         self.readFile(fileEntry);       }, self.onErrorCreateFile);     }, function (error) {       console.log('onErrorLoadFs, error:', error);     });   }   function readFile(fileEntry) {     let self = this;     fileEntry.file(function (file) {       var reader = new FileReader();       reader.onloadend = function() {         if(this.result === null) {           console.log('readFile unexpected this.result == null');           return;         }         console.log(typeof this.result);         console.log('Successful file read length: ', this.result.length);         // var blob = new Blob([new Uint8Array(this.result)], { type: "video/mpeg4" });         console.log('Successful file read: ', this.result);       };       // reader.readAsText(file);       reader.readAsArrayBuffer(file);       // reader.readAsBinaryString(file);     }, self.onErrorReadFile);   }  onErrorReadFile() {     console.log('Failed file read: ');   }
 
 
 
         
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

因安卓和ios下文件的存儲路徑不一樣,故需要做一個判斷,文件的存儲目錄

function getDirectory() {     let isIOS =/(iPad|iPhone|iPod)/g.test(navigator.userAgent);     if(isIOS) {       return cordova.file.documentsDirectory;     }else {       return cordova.file.dataDirectory + 'files/';     } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM