项目文件夹

文件
wehub-resource-sync 98e40dac97
CLI Smoke Test / smoke-test-linux (20) (push) Has been cancelled
CLI Smoke Test / smoke-test-linux (24) (push) Has been cancelled
CLI Smoke Test / smoke-test-windows (20) (push) Has been cancelled
CLI Smoke Test / smoke-test-windows (24) (push) Has been cancelled
Expo App TypeScript typecheck / typecheck (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:40:49 +08:00

30 行
1.3 KiB
TypeScript

/**
* Native (iOS/Android) impl: append a Uint8Array to FormData for a multipart
* upload. RN's Blob polyfill rejects `new Blob([arrayBuffer])`, so we stage
* the bytes to a temp file in cacheDirectory and use RN FormData's
* `{ uri, type, name }` form, which the platform multipart writer streams
* directly off disk. Returns a cleanup that deletes the temp file.
*/
import { encodeBase64 } from '@/encryption/base64';
import { writeAsStringAsync, deleteAsync, cacheDirectory, EncodingType } from 'expo-file-system/legacy';
import { randomUUID } from 'expo-crypto';
export async function appendFormFile(
formData: FormData,
bytes: Uint8Array,
field: string,
filename: string,
contentType: string,
): Promise<() => Promise<void>> {
if (!cacheDirectory) {
throw new Error('cacheDirectory unavailable on this platform');
}
const tempUri = `${cacheDirectory}happy-upload-${randomUUID()}`;
await writeAsStringAsync(tempUri, encodeBase64(bytes), { encoding: EncodingType.Base64 });
// RN typings don't know about the {uri, type, name} form, but the runtime does.
formData.append(field, { uri: tempUri, type: contentType, name: filename } as unknown as Blob);
return async () => {
try { await deleteAsync(tempUri, { idempotent: true }); } catch { /* best effort */ }
};
}