Search code examples
windowsasynchronouspromisewinjsdeep-copy

winJS Copy deepFolder Tree to install win8.1 app content


I'm actualy working on a windows 8.1 app in js and html, the app contain a very large number of big files that i need to install and update many times. So i 've dev a fct to make update from usb device to local data app folder. It's working fine, but my fct is not build with promises and it's not easy to follow progress and completition... So i'm working on a fully new fct, but it's not working ;o( can someone help me on the promise structure ?

My actual code :

app.copyTree = function (srcRootSorageFolder, destRootStorageFolder) {
    console.log('copy tree Start...');
    var fileToCopy = 0;
    var fileCopied = 0;
    var foldToCreate = 0;
    var foldCreated = 0;
    //-- init and wait promiseS ....
    scanFolder(srcRootSorageFolder, destRootStorageFolder).then(
            function () {
                console.log('successfull copy !!');
                console.log(fileCopied + ' fichier(s) copié(s) sur ' + fileToCopy);
                console.log(foldCreated + ' dossier(s) créé(s) sur ' + foldToCreate);
            },
            function error(error) {
                console.log('error copy' + error);                    
                console.log(fileCopied + ' fichier(s) copié(s) sur ' + fileToCopy);
                console.log(foldCreated + ' dossier(s) créé(s) sur ' + foldToCreate);
            }
    );

    //--sub fct with promise to scan a folder and launch copy
    function scanFolder(srcFoldStorage, destFoldStorage) {
        console.log('scanFolder Start...');
        var promises = [];
        return new WinJS.Promise(function (complete, error) {
            promises.push(
                srcFoldStorage.getFilesAsync().then(function (filesList) {
                    fileToCopy += filesList.size;
                    copyFiles(filesList, destFoldStorage);
                })
            );
            promises.push(
                srcFoldStorage.getFoldersAsync().then(function (foldersList) {
                    foldToCreate += foldersList.size;
                    loopSubFolder(foldersList, destFoldStorage);
                })
            );
            WinJS.Promise.join(promises).then(
                    function () {
                        complete();
                    },
                    error
            );
        });
    }


    //--sub fct with promise to copy all sub-folders in a folder to a destination
    function loopSubFolder(foldersList, destStorFolder) {
        console.log('loopSubFolder Start...');
        var promises = [];
        var collideOpt = Windows.Storage.CreationCollisionOption.openIfExists;
        return new WinJS.Promise(function (complete, error) {
            foldersList.forEach(function (reg) {
                var foldName = reg.name;
                promises.push(
                   destStorFolder.createFolderAsync(foldName, collideOpt).then(
                    function (newFoldStorage) {
                        foldCreated += 1;
                        scanFolder(reg, newFoldStorage);
                    })
                );
            });
            WinJS.Promise.join(promises).then(
                function () {
                    complete();
                },
                error
            );
        });
    };

    //--sub fct with promise to copy all file in a folder to a destination
    function copyFiles(filesList, destStorFolder) {
        console.log('copyFiles Start...');
        var promises = [];
        var collideOpt = Windows.Storage.CreationCollisionOption.replaceExisting;

        return new WinJS.Promise(function (complete, error) {
            filesList.forEach(function (reg) {
                var fName = reg.name;
                promises.push(
                   reg.copyAsync(destStorFolder, fName, collideOpt).then(fileCopied += 1)
                );
            });
            WinJS.Promise.join(promises).then(
                function () {
                    complete();
                },
                error
            );
        });
    };
    //--

};

Thanks for help

Mr


Solution

  • So, like promise and recursive are not really my friend...like god and evil... i've change my way to work and found a fully working and more simple solution.

    I've decided to search file in my source folder, and after to look the number of file completed... I don't know why i'm not using this solution at the beginning...This way, i can make a kind of progress and be sure that all files are done.

    If it can help another person with the same needs my code bellow :

    app.copyFolder = function (srcRootSorageFolder, destRootStorageFolder) {
        //srcRootSorageFolder & destRootStorageFolder need to be StorageFolder ( IAsyncOperation<StorageFolder>)
        var totalFiles = 0;     //total files to copy
        var totalSize = 0;      //total octects to copy
        var doneCopies = 0;     // files copy terminated    
        var doneSize = 0;       // octets copied
    
        //Prepare query to Search all files (deep search / recursive ) in the srcRootSorageFolder to follow progress
        var queryOptions = new Windows.Storage.Search.QueryOptions();
        queryOptions.folderDepth = Windows.Storage.Search.FolderDepth.deep;
        var query = srcRootSorageFolder.createFileQueryWithOptions(queryOptions);
    
    
        //--sub function to prepare progress (counting files and size)
        function prepareProgress(files) {
            var promises = [];
            return new WinJS.Promise(function (complete, error) {
                files.forEach(function (file) {
                    promises.push(                       
                        file.getBasicPropertiesAsync().then(function (props) {                           
                            totalFiles += 1;
                            totalSize += props.size;
                        })
                    )
                });                
                WinJS.Promise.join(promises).then(
                        function () {
                            complete(files);
                        },
                        error
                );
            });
        }
    
        //--sub function to copy files
        function copyFiles(files) {
            var promises = [];
            var folderCollideOpt = Windows.Storage.CreationCollisionOption.openIfExists;
            var fileCollideOpt = Windows.Storage.CreationCollisionOption.replaceExisting;
            return new WinJS.Promise(function (complete, error) {
                files.forEach(function (file) {
                    var destPath = file.path.split(srcRootSorageFolder.path);       // get the folder tree to create directory tree of the source folder in the dest folder
                    destPath = destPath[destPath.length - 1];                       //keeping last element of the array
                    destPath = destPath.substring(1, destPath.lastIndexOf('\\'));   //removing file name en 1st slash(\)
                    var fName = file.name;
                    promises.push(            
                        destRootStorageFolder.createFolderAsync(destPath, folderCollideOpt).then(
                            function (destStorage) {
                                //dest folder ready, initialising ... start copying file
                                file.copyAsync(destStorage, fName, fileCollideOpt).then(
                                    function (newFile) {
                                        updateProgress(file,newFile);
                                    });
                            }
                        )                        
                    )
                });
                WinJS.Promise.join(promises).then(
                        function () {
                            complete(files);
                        },
                        error
                );
            });
        }
        //--sub function to follow progress and defined if all copy are completed
        function updateProgress(file,newFile) {
            return new WinJS.Promise(function (complete, error) {
                newfiles.getBasicPropertiesAsync().then(function (newProps) { console.log('ok (copy):' + newfiles.name + ':' + newProps.size); });
                file.getBasicPropertiesAsync().then(function (props) {
                    doneCopies += 1;
                    doneSize += props.size;
                    console.log('ok (source):' + file.name + ':' + props.size);
                    //progress
                    var copiesProgress = Math.round((doneSize / totalSize) * 100 * 100) / 100; // copy percent with 2 decimals
                    console.log('progress: ' + copiesProgress + '%');
                    //completed action
                    if (doneCopies == totalFiles) {
                        console.log('Copy Done');
                    }
                });
            });
        }
    
        //--initialising process
        query.getFilesAsync().then(prepareProgress).then(copyFiles).then(console.log('Copy Start....'));
    
    
     };
    

    I hope you like, and if you have comments to make it better, i'll like ! Thanks

    Mr