XuqmGroup-RNSDK/packages/im/src/upload.ts

75 行
1.9 KiB
TypeScript

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<UploadResult> {
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)
}
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(() => '')
throw new Error(`[uploadFile] Upload failed (${response.status}): ${text}`)
}
const json = await response.json()
// 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,
}
}