2017-05-02 28 views
0

我有一个URL数组[URL1, URL2, URL3,...]:每个元素都是指向同一个文件的一个块的链接。每个块都是单独加密的,使用与所有其他块相同的密钥。在Array中推送ArrayBuffer以构造Blob

我用XMLHttpRequest下载每个块(在forEach函数中)。 onload

  1. 每个块首先被解密
  2. 然后每个块被转换成ArrayBuffersource
  3. 每个ArrayBuffer被推到一个数组(source
  4. 当三个第一步骤完成对于每个块(callbackvar递增到步骤#1 === array.length),使用数组
  5. blob i救过作为文件的FileReader与API & filesaver.js

如果它是一个大块的文件,一切工作正常。

但是对于多个块,步骤#1 &#2可以,但只有最后一个ArrayBuffer似乎被推送到数组。我错过了什么?

下面我的代码

// var for incrementation in forEach funtion 
var chunkdownloaded = 0; 
// 'clearfileurl' is the array of url's chunks :[URL1, URL2, URL3,...] 
clearfileurl.forEach(function(entry) { 
    var xhr = new XMLHttpRequest(); 
    var started_at = new Date(); 
    xhr.open('GET', entry, true); 
    xhr.responseType = 'text'; 

    // request progress 
    xhr.onprogress = function(pe) { 
     if (pe.lengthComputable) { 
      downloaderval.set((pe.loaded/pe.total) * 100); 
     } 
    }; 

    // on request's success 
    xhr.onload = function(e) { 
     if (this.status == 200) { 

      chunkdownloaded+=1; 
      var todecrypt = this.response; 

      // decrypt request's response: get a dataURI 
      try { 
       var bytesfile = CryptoJS.AES.decrypt(todecrypt.toString(), userKey); 
       var decryptedfile = bytesfile.toString(CryptoJS.enc.Utf8); 
      } catch(err) { 
       console.log (err); 
       return false; 
      } 

      //convert a dataURI to a Blob 
      var MyBlobBuilder = function() { 
       this.parts = []; 
      } 

      MyBlobBuilder.prototype.append = function(dataURI) { 
      //function dataURItoBlob(dataURI) { 
       // convert base64 to raw binary data held in a string 
       var byteString = atob(dataURI.split(',')[1]); 

       // separate out the mime component 
       // var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; 

       // write the bytes of the string to an ArrayBuffer 
       var ab = new ArrayBuffer(byteString.length); 
       var ia = new Uint8Array(ab); 
       for (var i = 0; i < byteString.length; i++) { 
        ia[i] = byteString.charCodeAt(i); 
       } 
       this.parts.push(ab); 
       console.log('parts', this.parts) 
       this.blob = undefined; // Invalidate the blob 
      } 

      MyBlobBuilder.prototype.getBlob = function() { 
       if (!this.blob) { 
        console.log (this.parts); 
        this.blob = new Blob(this.parts); 
       } 
       return this.blob; 
      }; 

      var myBlobBuilder = new MyBlobBuilder(); 
      myBlobBuilder.append(decryptedfile); 

      // if all chunks are downloaded 
      if (chunkdownloaded === clearfileurl.length) { 
       // get the blob 
       var FinalFile = myBlobBuilder.getBlob(); 

       // launch consturction of a file with'FinalFile' inside FileReader API 
       var reader = new FileReader(); 
       reader.onload = function(e){ 
        // build & save on client the final file with 'file-saver' library 
        var FileSaver = require('file-saver'); 
        var file = new File([FinalFile], clearfilename, {type: clearfiletype}); 
        FileSaver.saveAs(file); 
       }; 
       reader.readAsText(FinalFile); 

      } else { 
       console.log('not yet'); 
      } 
     } 
    }; 
    // sending XMLHttpRequest 
    xhr.send(); 
}); 
+1

那么你正在为每个xhr加载事件创建一个MyBlobBuilder实例,所以它们最终都将包含一个解密文件。在公共范围内(即在onload处理程序之外)仅创建此对象的一个​​实例,并仅在onload处理程序中调用其append方法。 (注意:我没有仔细阅读代码,所以可能会有其他一些错误,但这个更明显)。嗯,是的,没有什么能保证你的解密文件的附加顺序,所以你最好在forEach循环中附加一个对象,每完成一次就重建一次。 – Kaiido

+0

@Kaiido你说得对,고맙습니다。当然,我只需要在通用范围内创建一个MyBlobBuilder实例。你能否按照正确的顺序(原始URL数组中的一个:'[URL1,URL2,URL3,...]')重建解密文件数组? – Ontokrat

回答

1

你需要拿出的MyBlobBuilder声明,试试这个:

// var for incrementation in forEach funtion 
var chunkdownloaded = 0; 

//convert a dataURI to a Blob 
var MyBlobBuilder = function() { 
    this.parts = []; 
} 

MyBlobBuilder.prototype.append = function(dataURI, index) { 
//function dataURItoBlob(dataURI) { 
    // convert base64 to raw binary data held in a string 
    var byteString = atob(dataURI.split(',')[1]); 

    // separate out the mime component 
    // var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; 

    // write the bytes of the string to an ArrayBuffer 
    var ab = new ArrayBuffer(byteString.length); 
    var ia = new Uint8Array(ab); 
    for (var i = 0; i < byteString.length; i++) { 
     ia[i] = byteString.charCodeAt(i); 
    } 
    this.parts[index] = ab; 
    console.log('parts', this.parts) 
    this.blob = undefined; // Invalidate the blob 
} 

MyBlobBuilder.prototype.getBlob = function() { 
    if (!this.blob) { 
     console.log (this.parts); 
     this.blob = new Blob(this.parts); 
    } 
    return this.blob; 
}; 

var myBlobBuilder = new MyBlobBuilder(); 

// 'clearfileurl' is the array of url's chunks :[URL1, URL2, URL3,...] 
clearfileurl.forEach(function(entry, index) { 
    var xhr = new XMLHttpRequest(); 
    var started_at = new Date(); 
    xhr.open('GET', entry, true); 
    xhr.responseType = 'text'; 

    // request progress 
    xhr.onprogress = function(pe) { 
     if (pe.lengthComputable) { 
      downloaderval.set((pe.loaded/pe.total) * 100); 
     } 
    }; 

    // on request's success 
    xhr.onload = function(e) { 
     if (this.status == 200) { 

      chunkdownloaded+=1; 
      var todecrypt = this.response; 

      // decrypt request's response: get a dataURI 
      try { 
       var bytesfile = CryptoJS.AES.decrypt(todecrypt.toString(), userKey); 
       var decryptedfile = bytesfile.toString(CryptoJS.enc.Utf8); 
      } catch(err) { 
       console.log (err); 
       return false; 
      } 


      myBlobBuilder.append(decryptedfile, index); 

      // if all chunks are downloaded 
      if (chunkdownloaded === clearfileurl.length) { 
       // get the blob 
       var FinalFile = myBlobBuilder.getBlob(); 

       // launch consturction of a file with'FinalFile' inside FileReader API 
       var reader = new FileReader(); 
       reader.onload = function(e){ 
        // build & save on client the final file with 'file-saver' library 
        var FileSaver = require('file-saver'); 
        var file = new File([FinalFile], clearfilename, {type: clearfiletype}); 
        FileSaver.saveAs(file); 
       }; 
       reader.readAsText(FinalFile); 

      } else { 
       console.log('not yet'); 
      } 
     } 
    }; 
    // sending XMLHttpRequest 
    xhr.send(); 
}); 

*编辑我也更新了附加功能,以确保文件是在正确的顺序

+0

干净简洁的答案很好:特别感谢'额外'以确保文件的顺序正确 - 非常感谢。现在我在chunks函数中发现了一个问题(并非所有的块都被写入) - 另一个问题是...... – Ontokrat