apache / apache/cordova-plugin-file

Application crash with big data (JSON)

Open
#311 3 comments 0 reactions 0 assignees View on GitHub
bug platform: ios
Dominant language
JavaScript
Stars
744
Forks
754
Avg merge
3d 4h
Merged PRs (30d)
1

Description

# Bug Report

## Problem

### What is expected to happen?

The (big) data is correctly written in the file.

### What does actually happen?

The application crashes.

### 💡

I found a workaround but I think it remains an issue in the codebase (and could impact other developers). See below for the workaround.

## Information

I use:

* cordova-plugin-file
* react-native
* redux-persist

For the persistance (with redux-persist), I have a custom storage handler to write into a file.
The write part is very simple :

```typescript
function writeFile(fileEntry: FileEntry, data: any): Promise {
return new Promise((resolve, reject) => {
fileEntry.createWriter(writer => {
writer.onerror = reject
writer.onwriteend = resolve
writer.write(new Blob([JSON.stringify(data)], { type: 'text/plain' }))
}, reject)
})
}
```

However, with an evolution, our `data` passed from ~2Mo to ~20Mo. At this moment, the application crashes when saving the file.
It is the call to `writer.write` which seemed to cause the application to crash, if I build the Blob without saving it, I do not have any issue.

The size of the data before crash differs from IOS and ipad version.

### Workaround

I corrected (quick-win) the issue by doing so:

```typescript
function writeFile(fileEntry: FileEntry, data: any): Promise {
return new Promise((resolve, reject) => {
fileEntry.createWriter(writer => {
splitByChunks(JSON.stringify(data), 1000 * 1000) // 1Mo
// Ensure order of execution, could be improved
.reduce((acc, chunk) => acc.then(() => writeChunk(writer, chunk)), Promise.resolve())
.then(resolve)
.catch(reject)
}, reject)
})
}

function writeChunk(writer: FileWriter, chunk: string): Promise {
return new Promise((resolve, reject) => {
writer.onerror = reject
writer.onwriteend = resolve
writer.write(new Blob([chunk], { type: 'text/plain' }))
})
}

function splitByChunks(value: string, chunkLength: number): ReadonlyArray {
return Array(Math.ceil(value.length / chunkLength))
.fill(0)
.map((_, index) => value.slice(index * chunkLength, (index + 1) * chunkLength))
}
```

Although this correction works in my project there is an issue when the file is not totally written (application closed during write). I resolved it by ignoring incomplete file (= `JSON.parse` fails) because my project permits it.

### Environment, Platform, Device

* ipad4 / ios10
* ipad5 / ios12
* ipad6 / ios12

### Version information

* cordova: 8.1.2
* "cordova-browser": "5.0.1", // also tested on v6.0.1 - same issue
* "cordova-ios": "4.5.4",
* "cordova-plugin-file": "5.0.0",

## Checklist

- [x] I searched for existing GitHub issues
* Maybe related: #291, #297
- [x] I updated all Cordova tooling to most recent version
* But rolled back because of some incompatibilities in other parts of the application, issue still happening in last versions
- [x] I included all the necessary information above

Thanks for the plugin! 👍

Contributor guide

Open the contributing guide

Research direction

No source file or test is named in the report. Start by reproducing the crash at writer.write with roughly 20 MB of JSON on the listed iOS versions, comparing a single Blob write with the chunked workaround. Done means large data can be written without the application crashing and the resulting file remains complete.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, javascript, react-native, typescript
Domain
mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.