import Taro from '@tarojs/api' ; import { temporarilyNotSupport } from '../utils' ; import { CallbackManager } from '../utils/handler' ; import { convertObjectUrlToBlob , NETWORK_TIMEOUT , setHeader , XHR_STATS } from './utils' ; const createUploadTask = ( { url , filePath , formData , name , header , timeout , fileName , success , error } ) : Taro . UploadTask => { let timeoutInter ; let formKey ; const apiName = 'uploadFile' ; const xhr = new XMLHttpRequest ( ) ; const form = new FormData ( ) ; const callbackManager = { headersReceived : new CallbackManager ( ) , progressUpdate : new CallbackManager ( ) } ; xhr . open ( 'POST' , url ) ; setHeader ( xhr , header ) ; for ( formKey in formData ) { form . append ( formKey , formData [ formKey ] ) ; } xhr . upload . onprogress = e => { const { loaded , total } = e ; callbackManager . progressUpdate . trigger ( { progress : Math . round ( loaded / total * 100 ) , totalBytesSent : loaded , totalBytesExpectedToSent : total } ) ; } ; xhr . onreadystatechange = ( ) => { if ( xhr . readyState !== XHR_STATS . HEADERS_RECEIVED ) return ; callbackManager . headersReceived . trigger ( { header : xhr . getAllResponseHeaders ( ) } ) ; } ; xhr . onload = ( ) => { const status = xhr . status ; clearTimeout ( timeoutInter ) ; success ( { errMsg : `${ apiName }:ok` , statusCode : status , data : xhr . responseText || xhr . response } ) ; } ; xhr . onabort = ( ) => { clearTimeout ( timeoutInter ) ; error ( { errMsg : `${ apiName }:fail abort` } ) ; } ; xhr . onerror = ( e ) => { clearTimeout ( timeoutInter ) ; error ( { errMsg : `${ apiName }:fail ${ e . message }` } ) ; } ; /**
     * 中断任务
     */ const abort = ( ) => { clearTimeout ( timeoutInter ) ; xhr . abort ( ) ; } ; const send = ( ) => { xhr . send ( form ) ; timeoutInter = setTimeout ( ( ) => { xhr . onabort = null ; xhr . onload = null ; xhr . upload . onprogress = null ; xhr . onreadystatechange = null ; xhr . onerror = null ; abort ( ) ; error ( { errMsg : `${ apiName }:fail timeout` } ) ; } , timeout || NETWORK_TIMEOUT ) ; } ; convertObjectUrlToBlob ( filePath ) . then ( ( fileObj ) => { if ( ! fileName ) { fileName = typeof fileObj !== 'string' && fileObj . name ; } form . append ( name , fileObj , fileName || `file-${ Date . now ( ) }` ) ; send ( ) ; } ) . catch ( e => { error ( { errMsg : `${ apiName }:fail ${ e . message }` } ) ; } ) ; param { HeadersReceivedCallback } callback const onHeadersReceived = callbackManager . headersReceived . add ; param { HeadersReceivedCallback } callback const offHeadersReceived = callbackManager . headersReceived . remove ; param { ProgressUpdateCallback } callback const onProgressUpdate = callbackManager . progressUpdate . add ; param { ProgressUpdateCallback } callback const offProgressUpdate = callbackManager . progressUpdate . remove ; const headersReceived = temporarilyNotSupport ( 'UploadTask.headersReceived' ) ; const progress = temporarilyNotSupport ( 'UploadTask.progress' ) ; return { abort , onHeadersReceived , offHeadersReceived , onProgressUpdate , offProgressUpdate , headersReceived , progress } ; } ; /**
 * 将本地资源上传到服务器。客户端发起一个 HTTPS POST 请求，其中 content-type 为 multipart/form-data。使用前请注意阅读相关说明。
 */ export const uploadFile = ( { url , filePath , name , header , formData , timeout , fileName , success , fail , complete } ) => { let task ! ; const result = new Promise ( ( resolve , reject ) => { task = createUploadTask ( { url , header , name , filePath , formData , timeout , fileName , success : res => { success && success ( res ) ; complete && complete ( res ) ; resolve ( res ) ; } , error : res => { fail && fail ( res ) ; complete && complete ( res ) ; reject ( res ) ; } } ) ; } ) as any ; result . headersReceive = task . onHeadersReceived ; result . progress = task . onProgressUpdate ; result . abort = task . abort ; return result ; } ;