在Cordova中合并文件的多个部分

Merging multiple parts of a file in Cordova

本文关键字:个部 文件 Cordova 合并      更新时间:2023-09-26

在我的Cordova应用程序中,我正在下载任意文件,如图像或视频文件。这是用Cordova文件传输插件和"Range"Header完成的,因为我需要分部分下载文件。

我的问题是,我想把几个小的"字节"文件合并回原来的文件中——它们曾经在哪里使用过那个文件。每次我试图通过FileReader将结果部分读取为binaryString,并将它们一起写入一个新文件时,该文件最终会比原始文件的部分大得多,并且结果文件不可用。

感谢您的帮助。

这是我到现在为止的代码(又长又丑):

document.addEventListener('deviceready', deviceready, false);
var App;
var finishedFileUrl = "";
var async = {
    sequence: function(items, callback) {       
        var def = $.Deferred(),
        deferrers = [$.Deferred()];
        for(var i = 0; i < items.length; i++) {
            (function (n) {     
                deferrers[n + 1] = $.Deferred();
                deferrers[n].always(function() {
                    callback(items[n], deferrers[n + 1]);
                });
            })(i);  
        }
        deferrers[items.length].always(function() {
            def.resolve();
        });         
        deferrers[0].resolve();
        return def.promise();
    }
}
var aSmallImageArray = [
'' // Put URL to JPG accessible with Range Header Request here
];
var aByteSizeImageArray = [];
function formatDownloadArray(fileSize) {
    for(var j = 1000; j <= fileSize; j += 1000) {
        aByteSizeImageArray.push(j);
    }
    aByteSizeImageArray.push(j);
}
function deviceready() {
    console.log('dv ready');
    function registerHandlers() {
        App = new DownloadApp();
        formatDownloadArray(XXXXX);     // XXXXX should be size of JPG in bytes
        document.getElementById("startDl").onclick = function() {
            var that = this;
            console.log("load button clicked");
            var folderName = "testimagefolder";
            // sequence call
            async.sequence(aByteSizeImageArray, function(currentBytes, iter) {
                var filePath = aSmallImageArray[0];
                var fileName = aSmallImageArray[0].substr(52,99) + currentBytes;
                console.log(filePath);
                console.log(fileName);
                console.log("Starting with: " + fileName);
                var uri = encodeURI(filePath);
                var folderName = "testimagefolder";
                document.getElementById("statusPlace").innerHTML = "<br/>Loading: " + uri;
                App.load(currentBytes, uri, folderName, fileName,
                    function progress (percentage) {
                         document.getElementById("statusPlace").innerHTML = "<br/>" + percentage + "%";
                    },
                    function success (entry) {
                        console.log("Entry: " + entry);
                        document.getElementById("statusPlace").innerHTML = "<br/>Image saved to: " + App.filedir;
                        console.log("DownloadApp.filedir: " + App.filedir);
                        iter.resolve();
                    },
                    function error () {
                        document.getElementById("statusPlace").innerHTML = "<br/>Failed load image: " + uri;
                        iter.resolve();
                    }
                );              
            }).then(function afterAsync () {
                console.log("ASYNC DONE");
                var ohNoItFailed = function ohNoItFailed (exeperro) {
                    console.log(exeperro);
                }
                // now we merge the fileparts into one file to show it
                window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (FileSystem) {
                    FileSystem.root.getDirectory(folderName, {create: true, exclusive: false}, function itSuccessed (Directory) {
                        Directory.getFile(aSmallImageArray[0].substr(52,99), {create: true, exclusive: false}, function itSuccessedAgain (fileEntry) {
                            finishedFileUrl = fileEntry.toURL();
                            var directoryReader = Directory.createReader();
                            var allFiles = directoryReader.readEntries(function succesReadDir (fileEntries) {
                                async.sequence(fileEntries, function(currentFile, iterThis) {
                                    currentFile.file(function (theActualFile) {
                                        var myFileReader = new FileReader();
                                        myFileReader.onload = function (content) {
                                            console.log('FileReader onload event fired!');
                                            console.log('File Content should be: ' + content.target.result);
                                            fileEntry.createWriter(
                                            function mergeImage (writer) {
                                                writer.onwrite = function (evnt) {
                                                    console.log("Writing successful!");
                                                    iterThis.resolve();
                                                }
                                                writer.seek(writer.length);
                                                writer.write(content.target.result);
                                            }, ohNoItFailed);
                                        };
                                        myFileReader.readAsBinaryString(theActualFile);
                                    }, ohNoItFailed);
                                }).then(function afterAsyncTwo () {
                                    console.log("NOW THE IMAGE SHOULD BE TAKEN FROM THIS PATH: " + finishedFileUrl);
                                    //window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (FileSystem) {
                                        //FileSystem.root.getDirectory(folderName, {create: true, exclusive: false}, function itSuccessed (Directory) {
                                            //Directory.getFile(aSmallImageArray[0].substr(52,99), {create: true, exclusive: false}, function     itSuccessedAgain (fileEntry) {    
                                                //fileEntry.createWriter(    
                                        document.getElementById("image_here").src = finishedFileUrl;    
                                });    
                            }, ohNoItFailed);                               
                        }, ohNoItFailed);    
                    }, ohNoItFailed);    
                }, ohNoItFailed);                       
            });    
        };    
    }    
    registerHandlers();    
}    
var DownloadApp = function() {}
DownloadApp.prototype = {
    filedir: "",
    load: function(currentBytes, uri, folderName, fileName, progress, success, fail) {
        var that = this;
        that.progress = progress;
        that.success = success;
        that.fail = fail;
        filePath = "";
        that.getFilesystem(
                function(fileSystem) {
                    console.log("GotFS");
                    that.getFolder(fileSystem, folderName, function(folder) {
                        filePath = folder.toURL() + fileName;
                        console.log("FILEPATH: " + filePath);
                        console.log("URI: " + uri);
                        that.transferFile(currentBytes, uri, filePath, progress, success, fail);
                    }, function(error) {
                        console.log("Failed to get folder: " + error.code);
                        typeof that.fail === 'function' && that.fail(error);
                    });
                },
                function(error) {
                    console.log("Failed to get filesystem: " + error.code);
                    typeof that.fail === 'function' && that.fail(error);
                }
        );
    },
    getFilesystem: function (success, fail) {
        window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, success, fail);
    },
    getFolder: function (fileSystem, folderName, success, fail) {
        fileSystem.root.getDirectory(folderName, {create: true, exclusive: false}, success, fail)
    },
    transferFile: function (currentBytes, uri, filePath, progress, success, fail) {
        var that = this;
        that.progress = progress;
        that.success = success;
        that.fail = fail;
        console.log("here we go");
        console.log("filePath before Request: " + filePath);
        var previousBytes = currentBytes - 1000;
        var transfer = new FileTransfer();
        transfer.onprogress = function(progressEvent) {
            if (progressEvent.lengthComputable) {
                var perc = Math.floor(progressEvent.loaded / progressEvent.total * 100);
                typeof that.progress === 'function' && that.progress(perc); // progression on scale 0..100 (percentage) as number
            } else {
            }
        };
        transfer.download(
            uri,
            filePath,
            function success (entry) {
                console.log("File saved to: " + entry.toURL());
                typeof that.success === 'function' && that.success(entry);
            },
            function errorProblem(error) {
                console.log("An error has occurred: Code = " + error.code);
                console.log("download error source " + error.source);
                console.log("download error target " + error.target);
                console.log("download error code " + error.code);
                typeof that.fail === 'function' && that.fail(error);
            },
            true,
            {
                headers: {
                    "Range": "bytes=" +  previousBytes + "-" + currentBytes
                }
            }
        );
    }
}   

stackoverflow用户的异步代码:Paul Facklam->非常感谢!

您可以从其他blob构建blob,就像您现在使用FileReader的blob一样。(文件()为Blob)

// put three blobs into a fourth:
var b=new Blob([new Blob(["hello"]), new Blob([" "]), new Blob(["world"])]);
// verify the blob has the data we expect:
var fr=new FileReader();
fr.onload=function(){alert(this.result);};
fr.readAsBinaryString(b);  // shows: "hello world"

这里使用binaryString风格来显示这些低阶字符串是如何堆叠的,但实际的新blob实例应该具有原始blob的所有原始(任意)字节,即使它们不是由简单字符串组成的。。。

使用readAsArrayBuffer()而不是readAsBinaryString()成功了!

所以不是:

myFileReader.readAsBinaryString(theActualFile);

我做到了:

myFileReader.readAsBinaryArray(theActualFile);

并且生成的图像文件是可用的。