完全等待FileReader切片blob

时间:2015-02-07 14:44:48

标签: javascript html5 cryptojs

我试图用FileReader API读取文件数据,我在同样的问题上阅读了很多问题并试图实现他们的解决方案,但是对于我的代码中的一些错误(可能),它一直在做错的结果。为了避免在文件太大(超过15MB)时崩溃浏览器,我决定开始使用'切片'方法。但问题是,由于FileReader onload事件是异步的,所以我得到代码的一部分,它应该很快准备好已完成的缓冲区,当它仍然不完整时。而且我无法在onload事件中创建所有内容,因为它只有总缓冲区的一部分。这是我的代码:

function readBlob(opt_startByte, opt_stopByte) 
{
    var file = window.files[0];
    var start = parseInt(opt_startByte) || 0;
    var stop = parseInt(opt_stopByte) || file.size - 1;

    var reader = new FileReader();

    // If we use onloadend, we need to check the readyState.
    reader.onload = function(evt) {           
        window.bits.push(CryptoJS.AES.encrypt(evt.target.result, window.password)); 
    };
    var blob = file.slice(start, stop + 1);
    reader.readAsDataURL(blob);
}

function encrypt()
{
    window.files = document.getElementById('encrypt-input').files;
    if (!window.files.length) {
        alert('Please select a file!');
        return;
    }
    window.password = $('#key').val();
    window.bits = [];
    var startByte = 0;              
    var endByte = 0;
    while(startByte <= document.querySelector('input[type=file]').files[0].size - 1)
    {       
        endByte = startByte + 1024;
        readBlob(startByte, endByte);
        startByte = endByte;
        if (startByte >= document.querySelector('input[type=file]').files[0].size)
        {
            alert('Here I want the total array length:' + window.bits.length);      
        }   
    }   
            alert('Here I want the total array length:' + window.bits.length);          
}

正如你在上面看到的那样,我试过了:

    if (startByte >= document.querySelector('input[type=file]').files[0].size)
    {
        alert('Here I want the total array length:' + window.bits.length);      
    }   

但由于某种原因,我仍然得到长度为0。使用切片方法时如何处理整个缓冲区?另一个次要问题是:在onload事件中,我称之为同步函数&#39; CryptoJS.AES.encrypt&#39;,但由于此事件是异步的,我期待浏览器在处理时不会冻结缓冲到这个事件。有没有什么办法可以实现一些东西,以避免在处理文件时冻结浏览器?

2 个答案:

答案 0 :(得分:1)

似乎你需要这样做“同步方式”。你可以在这里找到文档 - &gt; http://www.w3.org/TR/FileAPI/#FileReaderSync。 我还发现了这个库 - FileReader.js(http://bgrins.github.io/filereader.js/),它不仅使您在使用FileReader时生活更轻松,而且还内置了使用同步方法同步读取文件的选项。 很抱歉,现在无法发布一些示例代码!无论如何,希望它有所帮助!

答案 1 :(得分:0)

发生这种情况的原因是reader.readAsDataURL()是异步的。您必须将回调传递给完成后调用的readBlob

function readBlob(opt_startByte, opt_stopByte, done) {
    ...
    reader.onload = function(evt) {           
        window.bits.push(CryptoJS.AES.encrypt(evt.target.result, window.password));
        done();
    };
    ...
}

function encrypt() {    
    ...
    var startByte = 0;              
    var endByte = 0;
    var callback = function(){
        alert('Here I want the total array length:' + window.bits.length);
    };
    while(startByte <= document.querySelector('input[type=file]').files[0].size - 1) {
        endByte = startByte + 1024;
        (function(startByte, endByte, newCallback){
            callback = function(){
                readBlob(startByte, endByte, newCallback);
            };
        })(startByte, endByte, callback);
        startByte = endByte;
    }
    callback(); // run the chain
}

没有其他合理的方法,因为JavaScript没有sleep函数。