UNPKG

@tarojs/taro-h5

Version:
155 lines (152 loc) • 5.34 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 settled = false; let formKey; const apiName = 'uploadFile'; const xhr = new XMLHttpRequest(); const form = new FormData(); const callbackManager = { headersReceived: new CallbackManager(), progressUpdate: new CallbackManager() }; const cleanup = () => { settled = true; clearTimeout(timeoutInter); xhr.onload = null; xhr.onabort = null; xhr.onerror = null; xhr.upload.onprogress = null; xhr.onreadystatechange = null; }; const fail = (message, abortRequest = false) => { if (settled) return; cleanup(); if (abortRequest) xhr.abort(); error({ errMsg: `${apiName}:fail ${message}` }); }; 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 = () => { if (settled) return; const status = xhr.status; cleanup(); success({ errMsg: `${apiName}:ok`, statusCode: status, data: xhr.responseText || xhr.response }); }; xhr.onabort = () => fail('abort'); xhr.onerror = (e) => fail(e.message); /** * 中断任务 */ const abort = () => fail('abort', true); const send = () => { timeoutInter = setTimeout(() => fail('timeout', true), timeout || NETWORK_TIMEOUT); xhr.send(form); }; convertObjectUrlToBlob(filePath) .then((fileObj) => { if (settled) return; if (!fileName) { fileName = typeof fileObj !== 'string' && fileObj.name; } form.append(name, fileObj, fileName || `file-${Date.now()}`); send(); }) .catch(e => { var _a, _b; return fail(String((_b = (_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : e === null || e === void 0 ? void 0 : e.status) !== null && _b !== void 0 ? _b : 'file conversion failed')); }); /** * 监听 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