@tarojs/taro-h5
Version:
Taro h5 framework
155 lines (152 loc) • 5.34 kB
JavaScript
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