import { getConfig, _getToken } from '@xuqm/rn-common' export interface UploadResult { url: string thumbnailUrl: string | null hash: string size: number originalName: string mimeType: string ext?: string } /** * Upload a file to the file-service using multipart/form-data. * Optionally attach a pre-generated thumbnail (for video files). * Requires an active IM session (Bearer token) for authentication. */ export async function uploadFile( localUri: string, mimeType: string, filename: string, thumbnailUri?: string, ): Promise { const config = getConfig() const token = await _getToken() if (!token) { throw new Error('[uploadFile] No active session — call ImSDK.login() first.') } const form = new FormData() // React Native FormData accepts an object with uri/name/type for file parts form.append('file', { uri: localUri, name: filename, type: mimeType, } as unknown as Blob) if (thumbnailUri) { form.append('thumbnail', { uri: thumbnailUri, name: 'thumbnail.jpg', type: 'image/jpeg', } as unknown as Blob) } if (config.debug) { console.debug('[XuqmSDK][Upload] request', { url: `${config.fileServiceUrl}/api/file/upload`, filename, mimeType, hasThumbnail: Boolean(thumbnailUri), }) } const response = await fetch(`${config.fileServiceUrl}/api/file/upload`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, // Do NOT set Content-Type — let fetch set it with the correct boundary }, body: form, }) if (!response.ok) { const text = await response.text().catch(() => '') if (config.debug) { console.debug('[XuqmSDK][Upload] response', { status: response.status, ok: false, body: text, }) } throw new Error(`[uploadFile] Upload failed (${response.status}): ${text}`) } const json = await response.json() if (config.debug) { console.debug('[XuqmSDK][Upload] response', { status: response.status, ok: true, }) } // Server wraps result in ApiResponse { code, data, message } const data = json?.data ?? json return { url: data.url, thumbnailUrl: data.thumbnailUrl ?? null, hash: data.hash, size: data.size, originalName: data.originalName, mimeType: data.mimeType, ext: data.ext, } }