From bb120118dc2fd8036f8af327dd6ce3f364f3730c Mon Sep 17 00:00:00 2001 From: Johann Schopplich Date: Wed, 29 Nov 2023 11:09:30 +0100 Subject: [PATCH] fix: form data serialization with multiple values fixes #60 --- src/runtime/formData.ts | 50 ++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/runtime/formData.ts b/src/runtime/formData.ts index 1e58d0d..5e210a4 100644 --- a/src/runtime/formData.ts +++ b/src/runtime/formData.ts @@ -3,12 +3,15 @@ export interface SerializedBlob { type: string size: number name?: string + __type: 'blob' } -export type SerializedFormData = Record< - string, - string | (SerializedBlob & { __type: 'blob' }) -> +export type SerializedFormDataValue = string | SerializedBlob | (string | SerializedBlob)[] + +export interface SerializedFormData { + [key: string]: SerializedFormDataValue + __type: 'form-data' +} export function isFormData(obj: unknown): obj is FormData { return obj instanceof FormData @@ -30,14 +33,26 @@ export async function formDataToObject(formData: FormData) { for (const [key, value] of formData.entries()) { if (value instanceof Blob) { - obj[key] = { - __type: 'blob', + const serializedBlob: SerializedBlob = { ...(await serializeBlob(value)), name: value.name, + __type: 'blob', } + + if (Array.isArray(obj[key])) + (obj[key] as SerializedBlob[]).push(serializedBlob) + else if (obj[key]) + obj[key] = [obj[key] as SerializedBlob, serializedBlob] + else + obj[key] = serializedBlob } else { - obj[key] = value + if (Array.isArray(obj[key])) + (obj[key] as string[]).push(value) + else if (obj[key]) + obj[key] = [obj[key] as string, value] + else + obj[key] = value } } @@ -49,9 +64,19 @@ export async function objectToFormData(obj: SerializedFormData) { const entries = Object.entries(obj).filter(([key]) => key !== '__type') for (const [key, value] of entries) { - if (isSerializedBlob(value)) { - const arrayBuffer = Uint8Array.from(atob(value.data), c => c.charCodeAt(0)) - const blob = new Blob([arrayBuffer], { type: value.type }) + if (Array.isArray(value)) { + for (const item of value) { + if (isSerializedBlob(item)) { + const blob = await deserializeBlob(item) + formData.append(key, blob, item.name) + } + else { + formData.append(key, item) + } + } + } + else if (isSerializedBlob(value)) { + const blob = await deserializeBlob(value) formData.append(key, blob, value.name) } else { @@ -83,3 +108,8 @@ async function serializeBlob(blob: Blob) { size: blob.size, } } + +async function deserializeBlob(serializedBlob: SerializedBlob) { + const arrayBuffer = Uint8Array.from(atob(serializedBlob.data), c => c.charCodeAt(0)) + return new Blob([arrayBuffer], { type: serializedBlob.type }) +}