Skip to content

Commit a4fa526

Browse files
authored
fix(app, app-shell): handle binary data transfer over USB/IPC for images (#20299)
Closes RQA-4941 Axios cannot return Blob types when in a Node.js environment (there is no native blob type in the version of Axios we use), and Electron's IPC mechanism does not properly serialize Blob objects into strings anyway. To fix, on the node layer we can request an ArrayBuffer type instead, transform it to an Array type, and then send this data across the IPC as it becomes perfectly serializable. We can then parse this Array type back into a Blob on the browser layer. Note that downloading images works perfectly fine - it's just an issue whenever we request the raw image files themselves.
1 parent 62d016d commit a4fa526

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

app-shell/src/usb.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,23 @@ async function usbListener(
133133
...config,
134134
data,
135135
headers: { ...config.headers, ...formHeaders },
136+
// Axios can't create proper blob types on the node layer, so we use
137+
// arraybuffer instead.
138+
responseType:
139+
config.responseType === 'blob' ? 'arraybuffer' : config.responseType,
136140
})
137141
usbLog.silly(`${config.method} ${config.url} resolved ok`)
142+
143+
// Convert ArrayBuffer to regular Array for IPC transfer, since ArrayBuffer
144+
// objects cannot be sent across the IPC reliably.
145+
const responseData =
146+
config.responseType === 'blob' && response.data instanceof ArrayBuffer
147+
? Array.from(new Uint8Array(response.data))
148+
: response.data
149+
138150
return {
139151
error: null,
140-
data: response.data,
152+
data: responseData,
141153
status: response.status,
142154
statusText: response.statusText,
143155
}

app/src/redux/shell/remote.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ export async function appShellRequestor<Data>(
6161
if (result?.error != null) {
6262
throw result.error
6363
}
64+
65+
// Blob data doesn't serialize properly across the IPC, so we parse it from
66+
// an Array type sent from the shell layer.
67+
if (config.responseType === 'blob' && Array.isArray(result.data)) {
68+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
69+
const uint8Array = new Uint8Array(result.data)
70+
result.data = new Blob([uint8Array]) as Data
71+
}
72+
6473
return result
6574
}
6675

0 commit comments

Comments
 (0)