import type { UploadToken, UploadOptions, UploadResult } from './types' export async function uploadToAliyunOSS( token: UploadToken, file: File, options: UploadOptions = {} ): Promise { const filename = options.filename || file.name const postdata: Record = { key: token.token_data.dir + filename, policy: token.token_data.policy, OSSAccessKeyId: token.token_data.accessid, success_action_status: '200', signature: token.token_data.signature, file: file, } const formdata = new FormData() for (const key in postdata) { formdata.append(key, postdata[key]) } const url = token.token_data.host const xhr = new XMLHttpRequest() xhr.open('POST', url, true) // 进度监听 xhr.upload.addEventListener('progress', (e) => { if (options.onProgress && e.lengthComputable) { const percent = e.loaded / e.total options.onProgress(percent) } }) return new Promise((resolve, reject) => { xhr.addEventListener('load', (e) => { options.onSuccess?.(e) resolve({ upload_id: token.id, filename }) }) xhr.addEventListener('error', (e) => { options.onError?.(e) reject(e) }) xhr.addEventListener('abort', (e) => { options.onError?.(e) reject(e) }) xhr.addEventListener('readystatechange', () => { if (xhr.readyState === 4 && xhr.status !== 200) { const error = new Error(`Upload failed with status ${xhr.status}`) options.onError?.(error) reject(error) } }) // 支持取消 options.signal?.addEventListener('abort', () => { xhr.abort() reject(new Error('Upload aborted')) }) xhr.send(formdata) }) }