/** * Upload API for file uploads via proxy to MinIO * Supports both Web and Native platforms */ import { Platform } from "react-native" const OSS_BASE_URL = "https://oss.upay01.com" // Upload response type export interface UploadResponse { code: number message: string data?: { filename: string originalName: string size: number mimetype: string url: string } } /** * Convert a URI to Blob (for Web platform) */ async function uriToBlob(uri: string): Promise { const response = await fetch(uri) const blob = await response.blob() return blob } /** * Upload file on Web platform */ async function uploadFileWeb( uri: string, fileName: string, mimeType: string, ): Promise<{ kind: "ok"; url: string } | { kind: "error"; message: string }> { try { // Convert URI to Blob for Web const blob = await uriToBlob(uri) const file = new File([blob], fileName, { type: mimeType }) const formData = new FormData() formData.append("file", file) const response = await fetch(`${OSS_BASE_URL}/api/proxy/upload`, { method: "POST", body: formData, }) const data: UploadResponse = await response.json() if (response.ok && data.code === 200 && data.data?.url) { return { kind: "ok", url: data.data.url } } else { return { kind: "error", message: data.message || "Upload failed" } } } catch (e) { if (__DEV__ && e instanceof Error) { console.error(`Upload error: ${e.message}`) } return { kind: "error", message: "Upload failed" } } } /** * Upload file on Native platform (iOS/Android) */ function uploadFileNative( uri: string, fileName: string, mimeType: string, ): Promise<{ kind: "ok"; url: string } | { kind: "error"; message: string }> { return new Promise((resolve) => { try { const xhr = new XMLHttpRequest() xhr.onload = () => { if (__DEV__) { console.log("Upload response status:", xhr.status) console.log("Upload response body:", xhr.responseText) } if (xhr.status === 200) { try { const response: UploadResponse = JSON.parse(xhr.responseText) if (response.code === 200 && response.data?.url) { resolve({ kind: "ok", url: response.data.url }) } else { resolve({ kind: "error", message: response.message || "Upload failed" }) } } catch { resolve({ kind: "error", message: "Invalid response" }) } } else { if (__DEV__) { console.log("Upload failed - Status:", xhr.status, "Response:", xhr.responseText) } resolve({ kind: "error", message: `Upload failed with status ${xhr.status}` }) } } xhr.onerror = () => { resolve({ kind: "error", message: "Network error" }) } xhr.ontimeout = () => { resolve({ kind: "error", message: "Upload timeout" }) } xhr.open("POST", `${OSS_BASE_URL}/api/proxy/upload`) xhr.timeout = 60000 // React Native specific FormData format const formData = new FormData() formData.append("file", { uri: uri, type: mimeType, name: fileName, } as any) xhr.send(formData) } catch (e) { if (__DEV__ && e instanceof Error) { console.error(`Upload error: ${e.message}`) } resolve({ kind: "error", message: "Upload failed" }) } }) } /** * Upload a file to OSS storage * Automatically handles Web vs Native platform differences * @param uri - Local file URI * @param fileName - File name * @param mimeType - MIME type of the file * @returns Upload result with URL or error */ export async function uploadFile( uri: string, fileName: string, mimeType: string, ): Promise<{ kind: "ok"; url: string } | { kind: "error"; message: string }> { if (Platform.OS === "web") { return uploadFileWeb(uri, fileName, mimeType) } else { return uploadFileNative(uri, fileName, mimeType) } }