最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I prevent Android downloads from failing? - Stack Overflow

programmeradmin1浏览0评论

I am using Cordova 12 to modify an existing Android application in order to try and make it compatible with Android API 34 (Android 14). The app must download thousands of small images before being usable, as the point of the app is to be used when totally offline. Therefore, linking directly to online images is not possible.

The problem is that some of the files will be saved to disk with a size of 0 byte. The specific files vary between runs. There is no error during the download or file saving process, ot at least the error callback is not triggered. I have tried adding a delay between file downloads, but it's not clear if it helped or not.

Here is the FileUtility class, that is used for downloading and saving the files to disk

import ErrorLog from "./error-log.cls";
const { log } = ErrorLog;
const { logError } = ErrorLog;

export default class FileUtility {
    static DEFAULT_ERROR_MESSAGE = 'UNKNOWN_ERROR';
    static ErrorCodesStrings = {
        1: 'NOT_FOUND_ERR',
        2: 'SECURITY_ERR',
        3: 'ABORT_ERR',
        4: 'NOT_READABLE_ERR',
        5: 'ENCODING_ERR',
        6: 'NO_MODIFICATION_ALLOWED_ERR',
        7: 'INVALID_STATE_ERR',
        8: 'SYNTAX_ERR',
        9: 'INVALID_MODIFICATION_ERR',
        10: 'QUOTA_EXCEEDED_ERR',
        11: 'TYPE_MISMATCH_ERR',
        12: 'PATH_EXISTS_ERR',
    };

    constructor() {}

    static getErrorText(errorCode) {
        if(errorCode && Number.isInteger(errorCode) && errorCode > 1 && errorCode < 13) {
            return FileUtility.ErrorCodesStrings[errorCode] + ` (code ${errorCode})`;
        }

        return FileUtility.DEFAULT_ERROR_MESSAGE + ` (code ${errorCode})`;
    }

    static createDirectory(directoriesToCreate, callback, onError) {
        const directoriesChain = directoriesToCreate.trim('/').split('/');

        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, (fileSystem) => {
            const currentPathArray = [];
            let currentDirectoryCount = 0;
            directoriesChain.forEach(currentDirectory => {
                currentDirectoryCount++;
                currentPathArray.push(currentDirectory);
                fileSystem.root.getDirectory(currentPathArray.join('/'), { create: true }, (directoryEntry) => {
                    if(callback && currentDirectoryCount == directoriesChain.length) { callback(directoryEntry); }
                }, onError);
            });
        }, onError);
    }

    static createFile(filename, content, callback, onError) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, (fileSystem) => {
            fileSystem.root.getFile(filename, { create: true, exclusive: false }, (fileEntry) => {
                fileEntry.createWriter((fileWriter) => {
                    fileWriter.onwriteend = () => {
                        if (callback) { callback(fileEntry) };
                    };
                    fileWriter.onerror = (fileWriterError) => {
                        if (onError) {
                            onError(fileWriterError);
                        } else {
                            logError(`Could not create file ${filename}: ${FileUtility.getErrorText(fileWriterError.code)}.`);
                        }
                    };
                    fileWriter.write(content);
                });
            }, (fileCreationError) => {
                if (onError) {
                    onError(fileCreationError);
                } else {
                    logError(`Could not create ${filename}: ${FileUtility.getErrorText(fileCreationError.code)}.`);
                }
            });
        }, (fileSystemError) => {
            if (onError) {
                onError(fileSystemError);
            }else {
                logError(`downloadFile: Could not get the file system access required to create file ${filename}: ${FileUtility.getErrorText(fileSystemError.code)}.`);
            }
        });
    }

    static downloadFile(sourceURI, destinationPath, onComplete, onError) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, (fileSystem) => {
            fileSystem.root.getFile(destinationPath, { create: true, exclusive: false }, (dataFile) => {
                /* Using XMLHttpRequest gives the same end result.
                const fileRequest = new XMLHttpRequest();
                fileRequest.open("GET", encodeURI(sourceURI), true);
                fileRequest.responseType = 'blob';
                fileRequest.onload = (loadEvent) => {
                    const responseData = fileRequest.response;

                    if(responseData) {
                        dataFile.createWriter((fileWriter) => {
                            fileWriter.onwriteend = (fileWriteEvent) => {
                                log(`downloadFile: File ${dataFile.fullPath} was downloaded and saved.`);
                                if(onComplete) { onComplete(dataFile); }
                            };

                            fileWriter.onerror = (downloadError) => {
                                logError(`downloadFile: Could not download file ${sourceURI} to ${dataFile.fullPath}: ${FileUtility.getErrorText(downloadError.code)}.`);
                                if(onError) { onError(downloadError); }
                            };

                            fileWriter.write(responseData);
                        });
                    }
                };
                fileRequest.onerror = (downloadError) => {
                    logError(`downloadFile: Could not download file ${sourceURI} to ${dataFile.fullPath}: ${FileUtility.getErrorText(downloadError.code)}.`);
                    if(onError) { onError(downloadError); }
                }
                fileRequest.send(null);
                */
                fetch(encodeURI(sourceURI), {
                    method: "get",
                }).then(response => {
                    if(response.ok) {
                        response.blob().then((blobData) => {
                            dataFile.createWriter((fileWriter) => {
                                fileWriter.onwriteend = (fileWriteEvent) => {
                                    log(`downloadFile: File ${dataFile.fullPath} was downloaded and saved.`);
                                    if(onComplete) { onComplete(dataFile); }
                                };

                                fileWriter.onerror = (downloadError) => {
                                    logError(`downloadFile: Could not download file ${sourceURI} to ${dataFile.fullPath}: ${FileUtility.getErrorText(downloadError.code)}.`);
                                    if(onError) { onError(downloadError); }
                                };

                                fileWriter.write(blobData);
                            });
                        }).catch((responseError) => {
                            logError(`downloadFile: Could not download file ${sourceURI}: ${responseError.message}.`);
                        });
                    } else {
                        logError(`downloadFile: Could not download file ${sourceURI}: ${response.status}.`);
                    }
                }).catch(responseError => {
                    logError(`downloadFile: Could not download file ${sourceURI}: ${responseError.message}.`);
                });
            }, (fileCreationError) => {
                logError(`downloadFile: Could not create the file ${destinationPath}: ${FileUtility.getErrorText(fileCreationError.code)}.`);
                if(onError) { onError(fileCreationError); }
            });
        }, (fileSystemError) => {
            logError(`downloadFile: Could not get the file system access required to create file ${destinationPath}: ${FileUtility.getErrorText(fileSystemError.code)}.`);
            if(onError) { onError(fileSystemError); }
        });
    }

    static readTextFile(filePath, onRead, onError) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, (fileSystem) => {
            fileSystem.root.getFile(filePath, { create: true, exclusive: false }, (fileToRead) => {
                fileToRead.file((fileEntry) => {
                    const reader = new FileReader();
                    reader.onloadend = () => { if (onRead) onRead(reader.result); };
                    reader.readAsText(fileEntry);
                }, (fileReadError) => {
                    logError(`readTextFile: Could not read file ${filePath} (${JSON.stringify(fileReadError)}).`);
                    if(onError) { onError(fileReadError); }
                });
            });
        }, (fileReadError) => {
            logError(`readTextFile: Could not read file ${filePath} (${JSON.stringify(fileReadError)}).`);
            if(onError) { onError(fileReadError); }
        });
    }

    static deleteFile(filePath, onSuccess, onError) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, (fileSystem) => {
            fileSystem.root.getFile(filePath, { create: false, exclusive: false }, (fileToDelete) => {
                fileToDelete.remove((fileDeleted) => {
                    log(`The file ${filePath} was successfully deleted.`, ErrorLog.ERROR_LEVEL.WARNING);
                    if(onSuccess) { onSuccess(fileDeleted); }
                }, (fileDeletionError) => {
                    logError(`deleteFile: Could not deleted file ${filePath}: ${FileUtility.getErrorText(fileDeletionError.code)}).`);
                    if(onError) { onError(fileDeletionError); }
                });
            }, (fileGetError) => {
                logError(`deleteFile: Could not deleted file ${filePath}: ${FileUtility.getErrorText(fileGetError.code)}).`);
                if(onError) { onError(fileGetError); }
            });
        }, (fileSystemError) => {
            logError(`deleteFile: Could not deleted file ${filePath}: ${FileUtility.getErrorText(fileSystemError.code)}).`);
            if(onError) { onError(fileSystemError); }
        });
    }

    static readDirectory(directoryPath, onSuccess, onError) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, (fileSystem) => {
            fileSystem.root.getDirectory(directoryPath, { create: false, exclusive: false }, (directoryEntry) => {
                onSuccess(directoryEntry);
            }, (readDirectoryError) => {
                logError(`readDirectory: Could not read directory ${directoryPath}: ${FileUtility.getErrorText(readDirectoryError.code)}.`);
                if(onError) { onError(readDirectoryError); }
            })
        }, (fileSystemError) => {
            logError(`readDirectory: Could not get the file system access to read directory ${directoryPath}: ${FileUtility.getErrorText(fileSystemError.code)}.`);
            if(onError) { onError(fileSystemError); }
        });
    }
};

Here is the part of the code responsible for downloading the images:

/*
    this.listToDownload is an array of objects with the following structure:
        path: the remote path of the image on the server, which should also be used, after some tweaking, as a local path.
        state: the string "missing", "ok", "update" or "delete", in order to know what to do with the image.
        version: the version of the image, in order to check if that specific image must be downloaded or if it's already up to date.
*/

export default class ApplicationSynchronisation {
    [...]

    downloadNextElement() {
        if(this.nextToDownload) {
            // Display the progress percentage on the main window.
            this.onProgress(this._('updating'), parseFloat((1 - (this.listToDownload.length / this.listOriginalSize)).toFixed(4)));
            const action = this.nextToDownload.state != "delete" ? 'download' : 'delete';
            let path = this.nextToDownload.path.replace(/{lang}/gi, this.language);
            path = path.startsWith('./') ? path.substr(2) : path;
            path = path.lastIndexOf('|') != -1 ? path.substring(0, path.lastIndexOf('|')) : path;
            let localPath = path;

            if(localPath.endsWith('.json')) {
                localPath = localPath.replace(`/${this.language}/`, '/');
            }

            if(localPath.startsWith('dist/')) {
                localPath = localPath.substr(5);
            }

            if(this.listToDownload.length) {
                this.nextToDownload = this.listToDownload.pop();
            } else {
                delete this.nextToDownload;
            }

            if(action == 'download') {
                FileUtility.createDirectory(localPath.substring(0, localPath.lastIndexOf('/')), () => {
                    FileUtility.downloadFile(this.application.remoteUrl + path, localPath, () => this.downloadNextElement(), (downloadError) => {
                        logError(`Error while downloading file ${this.application.remoteUrl + path} to local path ${localPath}: ${FileUtility.getErrorText(downloadError.code)}.`);
                        setTimeout(() => this.downloadNextElement, 250);
                    });
                }, (directoryCreationError) => {
                    logError(`Could not create the following complete path: ${localPath.substring(0, localPath.lastIndexOf('/'))}: ${FileUtility.getErrorText(directoryCreationError.code)}`);
                    this.downloadNextElement();
                });
            } else {
                FileUtility.deleteFile(localPath, (() => this.downloadNextElement), (deleteError) => {
                    logError(`Error while deleting ${localPath}: ${FileUtility.getErrorText(deleteError.code)}.`);
                    this.downloadNextElement();
                });
            }
        } else {
            this.onComplete();
        }
    }

    onProgress(textToShow, percentCompletion) {
        log(`${textToShow} ${(percentCompletion * 100).toFixed(2)}%`);
        if(this.application.onSyncProgress) { this.application.onSyncProgress(textToShow, percentCompletion) };
    }

    onComplete() {
        if(! this.synchronised) {
            this.synchronised = true;
            log("App synchronised.");
            this.onProgress(this._('uptodate'), 1);
            // Process sync callback and switch to main app.
            [...]
        }
    }

    [...]
}

As mentioned in the code, I have tried using the fetch API or XMLHttpRequest. Both give the same result. Adding a delay (through setTimeout) seems to help, although I have not yet formerly calculated the percentage of files that are empty with different delays so I cannot say for sure.

How can I change the download process to ensure that all the files are properly downloaded? Should I just put back on the stack any file that is downloaded and that is 0 byte, even if don't know exactly why it was saved as en empty file?

I am using Cordova 12 to modify an existing Android application in order to try and make it compatible with Android API 34 (Android 14). The app must download thousands of small images before being usable, as the point of the app is to be used when totally offline. Therefore, linking directly to online images is not possible.

The problem is that some of the files will be saved to disk with a size of 0 byte. The specific files vary between runs. There is no error during the download or file saving process, ot at least the error callback is not triggered. I have tried adding a delay between file downloads, but it's not clear if it helped or not.

Here is the FileUtility class, that is used for downloading and saving the files to disk

import ErrorLog from "./error-log.cls";
const { log } = ErrorLog;
const { logError } = ErrorLog;

export default class FileUtility {
    static DEFAULT_ERROR_MESSAGE = 'UNKNOWN_ERROR';
    static ErrorCodesStrings = {
        1: 'NOT_FOUND_ERR',
        2: 'SECURITY_ERR',
        3: 'ABORT_ERR',
        4: 'NOT_READABLE_ERR',
        5: 'ENCODING_ERR',
        6: 'NO_MODIFICATION_ALLOWED_ERR',
        7: 'INVALID_STATE_ERR',
        8: 'SYNTAX_ERR',
        9: 'INVALID_MODIFICATION_ERR',
        10: 'QUOTA_EXCEEDED_ERR',
        11: 'TYPE_MISMATCH_ERR',
        12: 'PATH_EXISTS_ERR',
    };

    constructor() {}

    static getErrorText(errorCode) {
        if(errorCode && Number.isInteger(errorCode) && errorCode > 1 && errorCode < 13) {
            return FileUtility.ErrorCodesStrings[errorCode] + ` (code ${errorCode})`;
        }

        return FileUtility.DEFAULT_ERROR_MESSAGE + ` (code ${errorCode})`;
    }

    static createDirectory(directoriesToCreate, callback, onError) {
        const directoriesChain = directoriesToCreate.trim('/').split('/');

        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, (fileSystem) => {
            const currentPathArray = [];
            let currentDirectoryCount = 0;
            directoriesChain.forEach(currentDirectory => {
                currentDirectoryCount++;
                currentPathArray.push(currentDirectory);
                fileSystem.root.getDirectory(currentPathArray.join('/'), { create: true }, (directoryEntry) => {
                    if(callback && currentDirectoryCount == directoriesChain.length) { callback(directoryEntry); }
                }, onError);
            });
        }, onError);
    }

    static createFile(filename, content, callback, onError) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, (fileSystem) => {
            fileSystem.root.getFile(filename, { create: true, exclusive: false }, (fileEntry) => {
                fileEntry.createWriter((fileWriter) => {
                    fileWriter.onwriteend = () => {
                        if (callback) { callback(fileEntry) };
                    };
                    fileWriter.onerror = (fileWriterError) => {
                        if (onError) {
                            onError(fileWriterError);
                        } else {
                            logError(`Could not create file ${filename}: ${FileUtility.getErrorText(fileWriterError.code)}.`);
                        }
                    };
                    fileWriter.write(content);
                });
            }, (fileCreationError) => {
                if (onError) {
                    onError(fileCreationError);
                } else {
                    logError(`Could not create ${filename}: ${FileUtility.getErrorText(fileCreationError.code)}.`);
                }
            });
        }, (fileSystemError) => {
            if (onError) {
                onError(fileSystemError);
            }else {
                logError(`downloadFile: Could not get the file system access required to create file ${filename}: ${FileUtility.getErrorText(fileSystemError.code)}.`);
            }
        });
    }

    static downloadFile(sourceURI, destinationPath, onComplete, onError) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, (fileSystem) => {
            fileSystem.root.getFile(destinationPath, { create: true, exclusive: false }, (dataFile) => {
                /* Using XMLHttpRequest gives the same end result.
                const fileRequest = new XMLHttpRequest();
                fileRequest.open("GET", encodeURI(sourceURI), true);
                fileRequest.responseType = 'blob';
                fileRequest.onload = (loadEvent) => {
                    const responseData = fileRequest.response;

                    if(responseData) {
                        dataFile.createWriter((fileWriter) => {
                            fileWriter.onwriteend = (fileWriteEvent) => {
                                log(`downloadFile: File ${dataFile.fullPath} was downloaded and saved.`);
                                if(onComplete) { onComplete(dataFile); }
                            };

                            fileWriter.onerror = (downloadError) => {
                                logError(`downloadFile: Could not download file ${sourceURI} to ${dataFile.fullPath}: ${FileUtility.getErrorText(downloadError.code)}.`);
                                if(onError) { onError(downloadError); }
                            };

                            fileWriter.write(responseData);
                        });
                    }
                };
                fileRequest.onerror = (downloadError) => {
                    logError(`downloadFile: Could not download file ${sourceURI} to ${dataFile.fullPath}: ${FileUtility.getErrorText(downloadError.code)}.`);
                    if(onError) { onError(downloadError); }
                }
                fileRequest.send(null);
                */
                fetch(encodeURI(sourceURI), {
                    method: "get",
                }).then(response => {
                    if(response.ok) {
                        response.blob().then((blobData) => {
                            dataFile.createWriter((fileWriter) => {
                                fileWriter.onwriteend = (fileWriteEvent) => {
                                    log(`downloadFile: File ${dataFile.fullPath} was downloaded and saved.`);
                                    if(onComplete) { onComplete(dataFile); }
                                };

                                fileWriter.onerror = (downloadError) => {
                                    logError(`downloadFile: Could not download file ${sourceURI} to ${dataFile.fullPath}: ${FileUtility.getErrorText(downloadError.code)}.`);
                                    if(onError) { onError(downloadError); }
                                };

                                fileWriter.write(blobData);
                            });
                        }).catch((responseError) => {
                            logError(`downloadFile: Could not download file ${sourceURI}: ${responseError.message}.`);
                        });
                    } else {
                        logError(`downloadFile: Could not download file ${sourceURI}: ${response.status}.`);
                    }
                }).catch(responseError => {
                    logError(`downloadFile: Could not download file ${sourceURI}: ${responseError.message}.`);
                });
            }, (fileCreationError) => {
                logError(`downloadFile: Could not create the file ${destinationPath}: ${FileUtility.getErrorText(fileCreationError.code)}.`);
                if(onError) { onError(fileCreationError); }
            });
        }, (fileSystemError) => {
            logError(`downloadFile: Could not get the file system access required to create file ${destinationPath}: ${FileUtility.getErrorText(fileSystemError.code)}.`);
            if(onError) { onError(fileSystemError); }
        });
    }

    static readTextFile(filePath, onRead, onError) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, (fileSystem) => {
            fileSystem.root.getFile(filePath, { create: true, exclusive: false }, (fileToRead) => {
                fileToRead.file((fileEntry) => {
                    const reader = new FileReader();
                    reader.onloadend = () => { if (onRead) onRead(reader.result); };
                    reader.readAsText(fileEntry);
                }, (fileReadError) => {
                    logError(`readTextFile: Could not read file ${filePath} (${JSON.stringify(fileReadError)}).`);
                    if(onError) { onError(fileReadError); }
                });
            });
        }, (fileReadError) => {
            logError(`readTextFile: Could not read file ${filePath} (${JSON.stringify(fileReadError)}).`);
            if(onError) { onError(fileReadError); }
        });
    }

    static deleteFile(filePath, onSuccess, onError) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, (fileSystem) => {
            fileSystem.root.getFile(filePath, { create: false, exclusive: false }, (fileToDelete) => {
                fileToDelete.remove((fileDeleted) => {
                    log(`The file ${filePath} was successfully deleted.`, ErrorLog.ERROR_LEVEL.WARNING);
                    if(onSuccess) { onSuccess(fileDeleted); }
                }, (fileDeletionError) => {
                    logError(`deleteFile: Could not deleted file ${filePath}: ${FileUtility.getErrorText(fileDeletionError.code)}).`);
                    if(onError) { onError(fileDeletionError); }
                });
            }, (fileGetError) => {
                logError(`deleteFile: Could not deleted file ${filePath}: ${FileUtility.getErrorText(fileGetError.code)}).`);
                if(onError) { onError(fileGetError); }
            });
        }, (fileSystemError) => {
            logError(`deleteFile: Could not deleted file ${filePath}: ${FileUtility.getErrorText(fileSystemError.code)}).`);
            if(onError) { onError(fileSystemError); }
        });
    }

    static readDirectory(directoryPath, onSuccess, onError) {
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, (fileSystem) => {
            fileSystem.root.getDirectory(directoryPath, { create: false, exclusive: false }, (directoryEntry) => {
                onSuccess(directoryEntry);
            }, (readDirectoryError) => {
                logError(`readDirectory: Could not read directory ${directoryPath}: ${FileUtility.getErrorText(readDirectoryError.code)}.`);
                if(onError) { onError(readDirectoryError); }
            })
        }, (fileSystemError) => {
            logError(`readDirectory: Could not get the file system access to read directory ${directoryPath}: ${FileUtility.getErrorText(fileSystemError.code)}.`);
            if(onError) { onError(fileSystemError); }
        });
    }
};

Here is the part of the code responsible for downloading the images:

/*
    this.listToDownload is an array of objects with the following structure:
        path: the remote path of the image on the server, which should also be used, after some tweaking, as a local path.
        state: the string "missing", "ok", "update" or "delete", in order to know what to do with the image.
        version: the version of the image, in order to check if that specific image must be downloaded or if it's already up to date.
*/

export default class ApplicationSynchronisation {
    [...]

    downloadNextElement() {
        if(this.nextToDownload) {
            // Display the progress percentage on the main window.
            this.onProgress(this._('updating'), parseFloat((1 - (this.listToDownload.length / this.listOriginalSize)).toFixed(4)));
            const action = this.nextToDownload.state != "delete" ? 'download' : 'delete';
            let path = this.nextToDownload.path.replace(/{lang}/gi, this.language);
            path = path.startsWith('./') ? path.substr(2) : path;
            path = path.lastIndexOf('|') != -1 ? path.substring(0, path.lastIndexOf('|')) : path;
            let localPath = path;

            if(localPath.endsWith('.json')) {
                localPath = localPath.replace(`/${this.language}/`, '/');
            }

            if(localPath.startsWith('dist/')) {
                localPath = localPath.substr(5);
            }

            if(this.listToDownload.length) {
                this.nextToDownload = this.listToDownload.pop();
            } else {
                delete this.nextToDownload;
            }

            if(action == 'download') {
                FileUtility.createDirectory(localPath.substring(0, localPath.lastIndexOf('/')), () => {
                    FileUtility.downloadFile(this.application.remoteUrl + path, localPath, () => this.downloadNextElement(), (downloadError) => {
                        logError(`Error while downloading file ${this.application.remoteUrl + path} to local path ${localPath}: ${FileUtility.getErrorText(downloadError.code)}.`);
                        setTimeout(() => this.downloadNextElement, 250);
                    });
                }, (directoryCreationError) => {
                    logError(`Could not create the following complete path: ${localPath.substring(0, localPath.lastIndexOf('/'))}: ${FileUtility.getErrorText(directoryCreationError.code)}`);
                    this.downloadNextElement();
                });
            } else {
                FileUtility.deleteFile(localPath, (() => this.downloadNextElement), (deleteError) => {
                    logError(`Error while deleting ${localPath}: ${FileUtility.getErrorText(deleteError.code)}.`);
                    this.downloadNextElement();
                });
            }
        } else {
            this.onComplete();
        }
    }

    onProgress(textToShow, percentCompletion) {
        log(`${textToShow} ${(percentCompletion * 100).toFixed(2)}%`);
        if(this.application.onSyncProgress) { this.application.onSyncProgress(textToShow, percentCompletion) };
    }

    onComplete() {
        if(! this.synchronised) {
            this.synchronised = true;
            log("App synchronised.");
            this.onProgress(this._('uptodate'), 1);
            // Process sync callback and switch to main app.
            [...]
        }
    }

    [...]
}

As mentioned in the code, I have tried using the fetch API or XMLHttpRequest. Both give the same result. Adding a delay (through setTimeout) seems to help, although I have not yet formerly calculated the percentage of files that are empty with different delays so I cannot say for sure.

How can I change the download process to ensure that all the files are properly downloaded? Should I just put back on the stack any file that is downloaded and that is 0 byte, even if don't know exactly why it was saved as en empty file?

Share Improve this question asked Feb 3 at 14:50 InLibrolivierInLibrolivier 11 silver badge2 bronze badges 3
  • @mplungjan It is inside the this.downloadNextElement function. The next element to download is extracted from this.listToDownload once the paths have been copied from the current element to download. – InLibrolivier Commented Feb 3 at 15:42
  • Do setTimeout(() => this.downloadNextElement, 250); in the success too – mplungjan Commented Feb 3 at 15:57
  • @mplungjan Yes, that was basically it. Oops, it turns out that was pretty simple. I had to call the actual function by doing () => setTimeout(() => this.downloadNextElement(), 250); and everything worked. I think I could even remove the delay and things would keep flowing. I'll post an official answer shortly, in order to close the question in a satisfactory manner. Thanks for your help! – InLibrolivier Commented Feb 3 at 20:24
Add a comment  | 

1 Answer 1

Reset to default 0

So, as mentioned by @mplungjan, it turns out that my problem was linked to an error in the code. Instead of using (() => this.downloadNextElement) or (() => this.downloadNextElement), I should have used () => setTimeout(() => this.downloadNextElement(), 250). I even reduced the delay between downloads, without any issue. So the code ends up being:

[...]
            FileUtility.downloadFile(this.application.remoteUrl + path, localPath, () => setTimeout(() => this.downloadNextElement(), 100), (downloadError) => {
                logError(`Error while downloading file ${this.application.remoteUrl + path} to local path ${localPath}: ${FileUtility.getErrorText(downloadError.code)}.`);
                setTimeout(() => this.downloadNextElement(), 100);
            });
[...]
    } else {
        FileUtility.deleteFile(localPath, () => setTimeout(() => this.downloadNextElement(), 100), (deleteError) => {
            logError(`Error while deleting ${localPath}: ${FileUtility.getErrorText(deleteError.code)}.`);
            setTimeout(() => this.downloadNextElement(), 100);
        });
    }
[...]
发布评论

评论列表(0)

  1. 暂无评论