UNPKG

@tarojs/taro-h5

Version:
160 lines (157 loc) 5.14 kB
import { CallbackManager } from '../../utils/handler.js'; import { setHeader, XHR_STATS, NETWORK_TIMEOUT, convertObjectUrlToBlob } from './utils.js'; const createUploadTask = ({ url, filePath, formData = {}, name, header, timeout, fileName, withCredentials = true, success, error }) => { 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); xhr.withCredentials = !!withCredentials; 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, totalBytesExpectedToSend: 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}` }); }); /** * 监听 HTTP Response Header 事件。会比请求完成事件更早 * @param {HeadersReceivedCallback} callback HTTP Response Header 事件的回调函数 */ const onHeadersReceived = callbackManager.headersReceived.add; /** * 取消监听 HTTP Response Header 事件 * @param {HeadersReceivedCallback} callback HTTP Response Header 事件的回调函数 */ const offHeadersReceived = callbackManager.headersReceived.remove; /** * 监听进度变化事件 * @param {ProgressUpdateCallback} callback HTTP Response Header 事件的回调函数 */ const onProgressUpdate = callbackManager.progressUpdate.add; /** * 取消监听进度变化事件 * @param {ProgressUpdateCallback} callback HTTP Response Header 事件的回调函数 */ const offProgressUpdate = callbackManager.progressUpdate.remove; return { abort, onHeadersReceived, offHeadersReceived, onProgressUpdate, offProgressUpdate }; }; /** * 将本地资源上传到服务器。客户端发起一个 HTTPS POST 请求,其中 content-type 为 multipart/form-data。使用前请注意阅读相关说明。 */ const uploadFile = ({ url, filePath, name, header, formData, timeout, fileName, withCredentials, success, fail, complete }) => { let task; const result = new Promise((resolve, reject) => { task = createUploadTask({ url, header, name, filePath, formData, timeout, fileName, withCredentials, success: res => { success && success(res); complete && complete(res); resolve(res); }, error: res => { fail && fail(res); complete && complete(res); reject(res); } }); }); result.headersReceive = task.onHeadersReceived.bind(task); result.progress = task.onProgressUpdate.bind(task); const properties = {}; Object.keys(task).forEach(key => { properties[key] = { get() { return typeof task[key] === 'function' ? task[key].bind(task) : task[key]; } }; }); return Object.defineProperties(result, properties); }; export { uploadFile }; //# sourceMappingURL=upload.js.map