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

标签 javascript file cordova concatenation file-transfer

在我的 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)

// 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 的所有 orig(任意)字节,即使它们不是由简单字符串组成...

关于javascript - 在 Cordova 中合并一个文件的多个部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26386354/

相关文章:

android - jQuery mobile,检测用户何时向右滑动图像

javascript - componentDidUpdate() 内部的 setState()

javascript - Chart.js:无法获取 x 轴值的坐标,除非 x 轴具有完全相同的值

java - 从 CLASSPATH 中目录的子目录获取文件路径

java - 删除没有删除权限的文件

cordova - jQuery Mobile 在按钮单击事件上显示 native 选择菜单

javascript - JavaScript 中的用户 session 跟踪?

javascript - 如何禁用 div 中的 root ng-click 按钮?

python - 有没有办法在 Python 中快速 move 许多文件?

angularjs - 设备在线时如何将离线数据库与 Firebase 同步?