Skip to content

Commit 66b319e

Browse files
feat: enhance TakePicture and TakePictureAdvanced to support online uploads with nativePayload
1 parent 3f86d2f commit 66b319e

4 files changed

Lines changed: 40 additions & 6 deletions

File tree

packages/jsActions/mobile-resources-native/src/camera/TakePicture.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@ export async function TakePicture(
126126
const filename = /[^\/]*$/.exec(uri)![0];
127127
const filePathWithoutFileScheme = uri.replace("file://", "");
128128

129+
// Set nativePayload so the patched FormData.prototype.append in NativeFileBackend
130+
// replaces the blob value with { uri, name, type } for online uploads. The patch
131+
// reads the third append() argument (fileName) and writes it onto nativePayload.name,
132+
// which FormData.getParts() uses as the Content-Disposition filename.
133+
(blob as any).nativePayload = { uri: `file://${uri}`, name: filename, type: "*/*" };
134+
129135
mx.data.saveDocument(
130136
imageObject.getGuid(),
131137
filename,

packages/jsActions/mobile-resources-native/src/camera/TakePictureAdvanced.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,12 @@ export async function TakePictureAdvanced(
179179
const filename = /[^\/]*$/.exec(uri)![0];
180180
const filePathWithoutFileScheme = uri.replace("file://", "");
181181

182+
// Set nativePayload so the patched FormData.prototype.append in NativeFileBackend
183+
// replaces the blob value with { uri, name, type } for online uploads. The patch
184+
// reads the third append() argument (fileName) and writes it onto nativePayload.name,
185+
// which FormData.getParts() uses as the Content-Disposition filename.
186+
(blob as any).nativePayload = { uri: `file://${uri}`, name: filename, type: "*/*" };
187+
182188
mx.data.saveDocument(
183189
imageObject.getGuid(),
184190
filename,

packages/jsActions/nanoflow-actions-native/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66

77
## [Unreleased]
88

9+
- Fixed an issue where base64-to-image decoding was failing.
10+
11+
## [7.2.0] Nanoflow Commons - 2026-7-3
12+
913
- Close offline database connection before navigating between pages with OpenURL nanoflow action.
1014

1115
## [7.1.0] Nanoflow Commons - 2026-6-5

packages/jsActions/nanoflow-actions-native/src/other/Base64DecodeToImage.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// Other code you write will be lost the next time you deploy the project.
88
import { Base64 } from "js-base64";
99
import RNBlobUtil from "react-native-blob-util";
10+
import { NativeModules } from "react-native";
1011

1112
// BEGIN EXTRA CODE
1213
// END EXTRA CODE
@@ -45,21 +46,38 @@ export async function Base64DecodeToImage(base64: string, image: mendix.lib.MxOb
4546
}
4647

4748
// Create a temporary file path
48-
const tempPath = `${RNBlobUtil.fs.dirs.CacheDir}/temp_image_${Date.now()}.png`;
49+
const fileName = `image_${Date.now()}.png`;
50+
const tempPath = `${RNBlobUtil.fs.dirs.CacheDir}/${fileName}`;
4951

5052
// Write Base64 data to a temporary file
5153
await RNBlobUtil.fs.writeFile(tempPath, cleanBase64, "base64");
5254

53-
// Fetch the file as a blob
54-
const res = await fetch(`file://${tempPath}`);
55-
const blob = await res.blob();
55+
// Read the file into the native blob store so offline mode works:
56+
// NativeFileBackend.storeFile calls NativeFileSystem.save(blob.data, path)
57+
// and blob.close() — a plain object has no .data getter or .close(), which
58+
// crashes iOS via [NSInvocation invokeWithTarget:].
59+
const nativeBlob = await NativeModules.MxFileSystem.read(tempPath.replace("file://", ""));
60+
// Normalize: MxFileSystem.read may return 'length' instead of 'size'.
61+
const blobData = { ...(nativeBlob as any) };
62+
if (blobData.size === undefined && blobData.length !== undefined) {
63+
blobData.size = blobData.length;
64+
}
65+
const blob = new Blob();
66+
Object.assign(blob, { data: blobData });
67+
68+
// Set nativePayload so the patched FormData.prototype.append in NativeFileBackend
69+
// replaces the blob value with { uri, name, type } for online uploads. The patch
70+
// reads the third append() argument (fileName) and writes it onto nativePayload.name,
71+
// which FormData.getParts() uses as the Content-Disposition filename.
72+
(blob as any).nativePayload = { uri: `file://${tempPath}`, name: fileName, type: "image/png" };
73+
const fileBlob = blob as Blob;
5674

5775
return new Promise((resolve, reject) => {
5876
mx.data.saveDocument(
5977
image.getGuid(),
60-
"camera image",
78+
fileName,
6179
{},
62-
blob,
80+
fileBlob,
6381
() => {
6482
RNBlobUtil.fs.unlink(tempPath).catch(e => console.info("Temp file cleanup failed:", e));
6583
resolve(true);

0 commit comments

Comments
 (0)