在Array中推送ArrayBuffer以构建Blob

时间:2017-05-02 18:56:02

标签: javascript blob chunks

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

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

  1. 每个块首先被解密
  2. 然后将每个块转换为ArrayBuffersource
  3. 每个ArrayBuffer都会被推送到数组(source
  4. 当为每个块完成三个第一步(callbackvar在步骤#1 = array.length上递增“时,使用数组<构造一个blob / LI>
  5. 使用FileReader API&amp; amp; blob保存为文件filesaver.js
  6. 如果它是一个块的文件,一切正常。

    但是有多个块,步骤#1&amp; #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 个答案:

答案 0 :(得分: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();
});

* edit我还更新了append函数以确保文件的顺序正确