Javascript 如何在android上的phonegap中从本地文件创建Blob

Javascript 如何在android上的phonegap中从本地文件创建Blob,javascript,android,cordova,android-webview,blob,Javascript,Android,Cordova,Android Webview,Blob,我正在尝试从android上的phonegap应用程序向AmazonS3上传一个文件。我已经有了iOS的代码。但我在安卓系统上遇到了麻烦。问题是我不知道如何正确地创建Blob对象。在iOS上,我只是这样做: blob = new Blob([evt.target.result], {type: "image/png"}); 上传的很好。在android上,无法使用Blob构造函数(请参阅),但我无法使用WebKitBlobBuilder将文件数据正确地导入Blob对象 下面是我如何检索文件数据

我正在尝试从android上的phonegap应用程序向AmazonS3上传一个文件。我已经有了iOS的代码。但我在安卓系统上遇到了麻烦。问题是我不知道如何正确地创建
Blob
对象。在iOS上,我只是这样做:

blob = new Blob([evt.target.result], {type: "image/png"});
上传的很好。在android上,无法使用
Blob
构造函数(请参阅),但我无法使用
WebKitBlobBuilder
将文件数据正确地导入
Blob
对象

下面是我如何检索文件数据的方法,有两种方法,都能顺利通过,但S3上的结果文件是空的:

window.resolveLocalFileSystemURI(url, function(e){
    e.file(function(f){
        var reader = new FileReader();
        reader.onloadend = function(evt) {
        // This way also did not work:
        //    var builder = new WebKitBlobBuilder();
        //    builder.append(evt.target.result);
        //    blob = builder.getBlob("image/png");

            var blob = null;
            var builder = new WebKitBlobBuilder();
            for(var i = 0; i < evt.target.result.length; i++){
                builder.append(evt.target.result[i]);
            }
            blob = builder.getBlob("image/png");
            uploadToS3(filename, s3url, blob);
        };
        reader.readAsArrayBuffer(f);
    });
}, function(e){
    console.log("error getting file");
    error();
});
编辑
我通过记录
evt.target.result.byteLength
检查了文件大小,结果正常,因此
evt.target.result
包含图像数据。上传仍然存在问题-我检查了s3存储,文件大小为0,因此我没有正确构建
Blob

因此这毕竟是一个android错误,至少从2012年11月起就没有修复

以下是我发现的一篇与我的问题直接相关的文章:


它还为该bug提供了一种解决方法,即直接发送
ArrayBuffer
,而不创建
Blob
。在我的例子中,我必须直接发送
evt.target.result

使用blobuilder来表现得像新的Blob…如果我尝试上载
WebKitBlobBuilder
对象本身,就会上载一个包含
[object WebKitBlobBuilder]
内容的文本文件。预期的,因为它是一个构建器,而不是数据本身。你知道了吗?我认为您需要使用BlobBuilder,然后调用builder.getBlob()。尽管如此,我仍然存在这个问题,找不到一个能在我的4.1.2目标上实际工作的API…我找到了一个解决方法,并为这个问题添加了一个解释我所做的事情的答案。你对这种方法的内存消耗有何见解?是否会在任何时间点将整个文件读入内存(我对
Blob
的内部工作方式有点不熟悉,尤其是与XMLHTTPRequest和FormData结合使用)?如果使用
readAsArrayBuffer
读取文件,显然会将其复制到内存中,因此,内存消耗至少应等于目标文件大小。至于XMLHTTPRequest的内部操作,坦率地说,我不知道它是否有任何开销。@很抱歉,这不是我的博客,只是我在搜索解决方案时发现的一篇文章。可能作者认为这个问题不再相关了=)顺便说一句,我已经提供了答案中文章中的解决方法。
var uploadToS3 = function(filename, s3url, fileData) {
    var xhr = createCORSRequest('PUT', s3url);
    if(!xhr) {
        console.log('CORS not supported');
        error();
        return;
    }
    xhr.onload = function () {
        if(xhr.status == 200) {
            console.log('100% - Upload completed.');
            callback(filename); //callback defined in outer context
        }
        else {
            console.log('0% - Upload error: ' + xhr.status);
            console.log(xhr.responseText);
            error();
        }
    };
    xhr.onerror = function () {
        console.log(0, 'XHR error.');
        error();
    };
    xhr.upload.onprogress = function (e) {
        if(e.lengthComputable) {
            var percentLoaded = Math.round((e.loaded / e.total) * 100);
            var label = (percentLoaded == 100) ? 'Finalizing.' : 'Uploading.';
            console.log(percentLoaded + "% - " + label);
        }
    };
    xhr.setRequestHeader('Content-Type', "image/png");
    //xhr.setRequestHeader('x-amz-acl', 'public-read');
    xhr.send(fileData);
};