Skip to content

Commit

Permalink
Merge pull request #2 from ct-lh/main
Browse files Browse the repository at this point in the history
Support for larger files: save blobs in chunks
  • Loading branch information
Amphiluke authored Nov 29, 2022
2 parents ef579df + 04db387 commit e1f9d83
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 6 deletions.
13 changes: 10 additions & 3 deletions src/android/SaveDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.json.JSONException;

import java.io.FileOutputStream;
import java.nio.channels.FileChannel;

public class SaveDialog extends CordovaPlugin {
private static final int LOCATE_FILE = 1;
Expand All @@ -27,7 +28,7 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
if (action.equals("locateFile")) {
this.locateFile(args.getString(0), args.getString(1));
} else if (action.equals("saveFile")) {
this.saveFile(Uri.parse(args.getString(0)), args.getString(1));
this.saveFile(Uri.parse(args.getString(0)), args.getString(1), args.getBoolean(2));
} else {
return false;
}
Expand Down Expand Up @@ -63,12 +64,18 @@ public void onRestoreStateForActivityResult(Bundle state, CallbackContext callba
this.callbackContext = callbackContext;
}

private void saveFile(Uri uri, String data) {
private void saveFile(Uri uri, String data, boolean clearFile) {
try {
byte[] rawData = Base64.decode(data, Base64.DEFAULT);
ParcelFileDescriptor pfd = cordova.getActivity().getContentResolver().openFileDescriptor(uri, "w");
ParcelFileDescriptor pfd = cordova.getActivity().getContentResolver().openFileDescriptor(uri, "wa");
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());

try {
if (clearFile) {
FileChannel fChan = fileOutputStream.getChannel();
fChan.truncate(0);
}

fileOutputStream.write(rawData);
this.callbackContext.success(uri.toString());
} catch (Exception e) {
Expand Down
39 changes: 36 additions & 3 deletions www/android/SaveDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ let locateFile = (type, name) => new Promise((resolve, reject) => {
exec(resolve, reject, "SaveDialog", "locateFile", [type || "application/octet-stream", name]);
});

let saveFile = (uri, blob) => new Promise((resolve, reject) => {
let saveFile = (uri, blob, clearFile) => new Promise((resolve, reject) => {
let reader = new FileReader();
reader.onload = () => {
exec(resolve, reject, "SaveDialog", "saveFile", [uri, reader.result]);
exec(resolve, reject, "SaveDialog", "saveFile", [uri, reader.result, clearFile]);
};
reader.onerror = () => {
reject(reader.error);
Expand All @@ -21,11 +21,44 @@ let saveFile = (uri, blob) => new Promise((resolve, reject) => {
reader.readAsArrayBuffer(blob);
});

let saveFileInChunks = (uri, blob) => {
const BLOCK_SIZE = 1024 * 1024;
let writtenSize = 0;

function saveNextChunk(clearFile) {
const size = Math.min(BLOCK_SIZE, blob.size - writtenSize);
const chunk = blob.slice(writtenSize, writtenSize + size);

writtenSize += size;

return saveFile(uri, chunk, clearFile);
}

return new Promise(async (resolve, reject) => {
let i = 0;
let uri = '';
let error = null;

while(writtenSize < blob.size) {
[uri, error] = await saveNextChunk(i === 0).then((result) => [result, null]).catch((err) => [null, err]);

if (error !== null) {
reject(error);
return;
}

i++;
}

resolve(uri);
});
}

module.exports = {
saveFile(blob, name = "") {
return keepBlob(blob) // see the “resume” event handler below
.then(() => locateFile(blob.type, name))
.then(uri => saveFile(uri, blob))
.then(uri => saveFileInChunks(uri, blob))
.then(uri => {
clearBlob();
return uri;
Expand Down

0 comments on commit e1f9d83

Please sign in to comment.