You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cordova 12适配Android 14(API 34)时批量图片下载出现0字节文件的问题求助

Cordova 12适配Android 14(API 34)时批量图片下载出现0字节文件的问题求助

我目前正在用Cordova 12改造一款现有Android应用,目标是让它兼容Android 14(API 34)。这款应用的核心是支持完全离线使用,所以必须先下载数千张小图片才能正常运行,因此直接引用在线图片的方案不可行。

现在我遇到了一个棘手的问题:部分文件保存到磁盘后大小为0字节,而且每次运行时出问题的具体文件都不固定。奇怪的是,下载和文件保存过程中没有触发任何错误回调,至少我这边没有收到错误提示。我尝试过在文件下载操作之间增加延迟,但不确定这是否真的能解决问题。

下面是我用来处理文件下载和本地存储的FileUtility类代码:

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 get file system access to delete file ${filePath}: ${FileUtility.getErrorText(fileSystemError.code)}).`);
            if(onError) { onError(fileSystemError); }
        });
    }
}

备注:内容来源于stack exchange,提问作者InLibrolivier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 08:53:06