The Problem: Cordova Crashes When Downloading Large Files
If you've ever tried to download a large file (300MB+) in a Cordova Android app, you've probably faced the dreaded silent crash—no error message, just a dead app.
After hours of debugging, I realized the issue wasn't just the download—it was also how Cordova handles large file writes on Android. For more background on Android's file system, see Android's architecture.
Here's how I fixed it.
Solution Part 1: Properly Configure the API Request
First, ensure your HTTP request fetches the file as a Blob (not text or array buffer). This prevents memory issues when dealing with large files. For alternative approaches, check this StackOverflow discussion on network requests.
Code Example:
function requestFile(taskId) {
console.log('Requesting file for taskId:', taskId);
const oReq = new XMLHttpRequest();
oReq.open("GET", `http://YOUR_SERVER/path/${taskId}`, true);
oReq.responseType = "blob"; // Critical for large files!
oReq.onload = function () {
if (oReq.status === 200) {
const blob = oReq.response;
if (blob) {
console.log('File received:', blob);
saveMP3(blob, onSuccess, onError); // Handle the blob
} else {
console.error('No blob received');
}
} else {
console.error('Request failed:', oReq.status);
}
};
oReq.onerror = function () {
console.error('Network error');
};
oReq.send();
}
Key Points:
responseType: "blob"
– Ensures efficient binary handling.- Error handling – Prevents silent failures.
Solution Part 2: Save the File in Chunks (The Real Fix!)
Even with a correct download, Cordova's file system API can crash when writing large files. The fix? Write in small chunks instead of all at once. This approach is also discussed in this advanced HTTP plugin issue.
This specifically avoids the dreaded Android crash documented in this Cordova plugin issue and this StackOverflow thread:
E AndroidRuntime: at org.apache.cordova.file.LocalFilesystem.writeToFileAtURL(LocalFilesystem.java:384)
E AndroidRuntime: at org.apache.cordova.file.FileUtils.write(FileUtils.java:1144)
By breaking the file into smaller pieces, we prevent Cordova's native file plugin from overloading Android's I/O buffer—which is what triggers this crash. For more on Cordova's Android implementation, see cordova-android package.
The fix? Write in small chunks instead of all at once. For a visual guide, check out this Cordova tutorial.
Code Example:
function saveMP3(blob, successCallback, errorCallback) {
const chunkSize = 1024 * 1024; // 1MB chunks
let offset = 0;
const fileName = `file_${Date.now()}.mp3`;
window.resolveLocalFileSystemURL(
cordova.file.externalRootDirectory,
(fileSystem) => {
fileSystem.getDirectory('Download', { create: true }, (dirEntry) => {
dirEntry.getFile(fileName, { create: true }, (fileEntry) => {
fileEntry.createWriter((fileWriter) => {
function writeNextChunk() {
if (offset >= blob.size) {
successCallback(fileEntry.toURL());
return;
}
const chunk = blob.slice(offset, offset + chunkSize);
fileWriter.onwriteend = () => {
offset += chunkSize;
writeNextChunk();
};
fileWriter.write(chunk);
}
fileWriter.onerror = errorCallback;
writeNextChunk();
}, errorCallback);
}, errorCallback);
}, errorCallback);
},
errorCallback
);
}
Why This Works:
- Avoids memory overload – Writing in 1MB chunks prevents crashes.
- Better performance – Doesn't freeze the UI thread.
- Reliable saving – Handles network interruptions gracefully.
Final Thoughts
It's surprising that Cordova doesn't have built-in support for large file downloads. But with chunked writing, you can bypass Android's file system limitations. For enterprise solutions, IBM offers Cordova development tools, and Ubuntu has its own Cordova implementation.
For more debugging help, check out our guides on debugging techniques and JavaScript fundamentals.
Key Takeaways:
- Always use
responseType: "blob"
for large downloads. - Never write large files at once—split into chunks.
- Log everything—Android's silent crashes need debugging.
For converting downloaded audio files, see our audio conversion guide. Hope this saves you hours of frustration!
Permissions config.xml
Verify that your config.xml file contains these necessary permissions:
<platform name="android">
<config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
android:maxSdkVersion="30" />
</config-file>
<edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application">
<application android:usesCleartextTraffic="true" />
</edit-config>
</platform>