如何使用Cordova下载160GB大文件?XMLHttpRequest加载大文件无响应问题求助
如何使用Cordova下载160GB大文件?XMLHttpRequest加载大文件无响应问题求助
兄弟,你遇到的问题其实很典型——用XHR把160GB的文件直接加载成Blob,这完全超出了Cordova WebView的内存承受能力,直接导致进程崩溃或者无响应,连错误事件都来不及触发,所以只打印了个5就挂了。
问题根源
当你设置req.responseType = "blob"时,XHR会把整个文件先加载到内存里再触发后续事件。160GB的文件远超过移动设备WebView的内存上限(一般也就几百MB到几GB),系统直接就把进程掐了,自然不会触发任何回调,也没机会进入catch块。
解决方案:分块下载+边下边存
核心思路是不要一次性加载整个文件,而是把文件分成小块(比如10MB一块),每次只下载一段,下载完成后立刻写入本地文件,循环直到整个文件下载完毕。配合Cordova的cordova-plugin-file插件就能实现,这样不会占用大量内存。
具体实现步骤&代码示例
- 先获取本地存储目录,创建一个空文件用于写入
- 用
Range请求头分段请求文件内容 - 每下载一块就追加写入本地文件,更新偏移量后继续下载下一块
// 配置参数 const FILE_URL = "你的大文件地址"; const TOTAL_FILE_SIZE = 160 * 1024 * 1024 * 1024; // 160GB const CHUNK_SIZE = 10 * 1024 * 1024; // 每次下载10MB let currentOffset = 0; let targetFileEntry; // 第一步:初始化本地文件 function initLocalFile() { // 获取Cordova的外部数据目录(可根据需求换其他目录) window.resolveLocalFileSystemURL( cordova.file.externalDataDirectory, (dirEntry) => { dirEntry.getFile( "large_download_file.bin", { create: true, exclusive: false }, (fileEntry) => { targetFileEntry = fileEntry; console.log("本地文件创建完成,开始分块下载"); downloadNextChunk(); }, (err) => console.error("创建本地文件失败:", err) ); }, (err) => console.error("获取存储目录失败:", err) ); } // 第二步:下载下一块文件 function downloadNextChunk() { if (currentOffset >= TOTAL_FILE_SIZE) { console.log("✅ 整个文件下载完成!"); return; } // 计算当前块的起止字节 const endOffset = Math.min(currentOffset + CHUNK_SIZE - 1, TOTAL_FILE_SIZE - 1); const xhr = new XMLHttpRequest(); xhr.open("GET", FILE_URL, true); // 设置Range请求头,告诉服务器只返回指定区间的内容 xhr.setRequestHeader("Range", `bytes=${currentOffset}-${endOffset}`); xhr.responseType = "blob"; xhr.onload = () => { // 206是部分内容的状态码,200可能是最后一块或服务器不支持Range if (xhr.status === 206 || xhr.status === 200) { writeChunkToFile(xhr.response); } else { console.error(`分块下载失败,状态码: ${xhr.status}`); } }; xhr.onerror = (err) => console.error("分块请求出错:", err); xhr.send(); } // 第三步:将下载的块写入本地文件 function writeChunkToFile(blob) { targetFileEntry.createWriter( (writer) => { // 定位到当前偏移量,实现追加写入 writer.seek(currentOffset); writer.write(blob); writer.onwriteend = () => { currentOffset += blob.size; const progress = ((currentOffset / TOTAL_FILE_SIZE) * 100).toFixed(2); console.log(`📥 已下载${progress}%`); // 继续下载下一块 downloadNextChunk(); }; writer.onerror = (err) => console.error("写入文件失败:", err); }, (err) => console.error("获取文件写入器失败:", err) ); } // 启动下载 initLocalFile();
额外注意事项
- 服务器支持Range请求:先发送一个HEAD请求,检查服务器返回的
Accept-Ranges头是否为bytes,如果不支持Range,分块下载就无法进行。 - 权限配置:Cordova需要配置文件读写权限,Android在
config.xml中添加:
iOS需要在<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Android 10+ 可能需要额外配置Scoped Storage或MANAGE_EXTERNAL_STORAGE权限 -->info.plist中添加文件访问权限描述,比如NSPhotoLibraryAddUsageDescription。 - 后台下载:如果需要APP退到后台仍能下载,建议使用专门的Cordova插件(比如
cordova-plugin-background-downloader),这类插件调用原生系统的下载管理器,稳定性更高。
备注:内容来源于stack exchange,提问作者user3523426
相关产品推荐
相关产品推荐

