|
- export class LsjFile {
- constructor(data) {
- this.dom = null;
- // files.type = waiting(等待上传)|| loading(上传中)|| success(成功) || fail(失败)
- this.files = new Map();
- this.debug = data.debug || false;
- this.id = data.id;
- this.width = data.width;
- this.height = data.height;
- this.option = data.option;
- this.instantly = data.instantly;
- this.prohibited = data.prohibited;
- this.onchange = data.onchange;
- this.onprogress = data.onprogress;
- this.uploadHandle = this._uploadHandle;
- // #ifdef MP-WEIXIN
- this.uploadHandle = this._uploadHandleWX;
- // #endif
- }
-
-
- /**
- * 创建File节点
- * @param {string}path webview地址
- */
- create(path) {
- if (!this.dom) {
- // #ifdef H5
- let dom = document.createElement('input');
- dom.type = 'file'
- dom.value = ''
- dom.style.height = this.height
- dom.style.width = this.width
- dom.style.position = 'absolute'
- dom.style.top = 0
- dom.style.left = 0
- dom.style.right = 0
- dom.style.bottom = 0
- dom.style.opacity = 0
- dom.style.zIndex = 999
- dom.accept = this.prohibited.accept;
- if (this.prohibited.count > 1) {
- dom.multiple = 'multiple';
- }
- dom.onchange = event => {
- for (let file of event.target.files) {
- this.addFile(file);
- }
- this.dom.value = '';
- };
- this.dom = dom;
- // #endif
-
- // #ifdef APP-PLUS
- let styles = {
- top: '-100px',
- left: 0,
- width: '1px',
- height: '1px',
- background: 'transparent'
- };
- let extras = {
- debug: this.debug,
- instantly: this.instantly,
- prohibited: this.prohibited,
- }
- this.dom = plus.webview.create(path, this.id, styles,extras);
- this.setData(this.option);
- this._overrideUrlLoading();
- // #endif
- return this.dom;
- }
- }
-
- copyObject(obj) {
- if (typeof obj !== "undefined") {
- return JSON.parse(JSON.stringify(obj));
- } else {
- return obj;
- }
- }
-
- /**
- * 自动根据字符串路径设置对象中的值 支持.和[]
- * @param {Object} dataObj 数据源
- * @param {String} name 支持a.b 和 a[b]
- * @param {String} value 值
- * setValue(dataObj, name, value);
- */
- setValue(dataObj, name, value) {
- // 通过正则表达式 查找路径数据
- let dataValue;
- if (typeof value === "object") {
- dataValue = this.copyObject(value);
- } else {
- dataValue = value;
- }
- let regExp = new RegExp("([\\w$]+)|\\[(:\\d)\\]", "g");
- const patten = name.match(regExp);
- // 遍历路径 逐级查找 最后一级用于直接赋值
- for (let i = 0; i < patten.length - 1; i++) {
- let keyName = patten[i];
- if (typeof dataObj[keyName] !== "object") dataObj[keyName] = {};
- dataObj = dataObj[keyName];
- }
- // 最后一级
- dataObj[patten[patten.length - 1]] = dataValue;
- this.debug&&console.log('参数更新后',JSON.stringify(this.option));
- }
-
- /**
- * 设置上传参数
- * @param {object|string}name 上传参数,支持a.b 和 a[b]
- */
- setData() {
- let [name,value = ''] = arguments;
- if (typeof name === 'object') {
- Object.assign(this.option,name);
- }
- else {
- this.setValue(this.option,name,value);
- }
-
- this.debug&&console.log(JSON.stringify(this.option));
-
- // #ifdef APP-PLUS
- this.dom.evalJS(`vm.setData('${JSON.stringify(this.option)}')`);
- // #endif
- }
-
- /**
- * 上传
- * @param {string}name 文件名称
- */
- async upload(name='') {
- if (!this.option.url) {
- throw Error('未设置上传地址');
- }
-
- // #ifndef APP-PLUS
- if (name && this.files.has(name)) {
- await this.uploadHandle(this.files.get(name));
- }
- else {
- for (let item of this.files.values()) {
- if (item.type === 'waiting' || item.type === 'fail') {
- await this.uploadHandle(item);
- }
- }
- }
- // #endif
-
- // #ifdef APP-PLUS
- this.dom&&this.dom.evalJS(`vm.upload('${name}')`);
- // #endif
- }
-
- // 选择文件change
- addFile(file) {
-
- let name = file.name;
- this.debug&&console.log('文件名称',name,'大小',file.size);
-
- if (file) {
- // 限制文件格式
- let path = '';
- let suffix = name.substring(name.lastIndexOf(".")+1).toLowerCase();
- let formats = this.prohibited.formats.toLowerCase();
- if (formats&&!formats.includes(suffix)) {
- this.toast(`不支持上传${suffix.toUpperCase()}格式文件`);
- return false;
- }
- // 限制文件大小
- if (file.size > 1024 * 1024 * Math.abs(this.prohibited.size)) {
- this.toast(`附件大小请勿超过${this.prohibited.size}M`)
- return false;
- }
- // #ifndef MP-WEIXIN
- path = URL.createObjectURL(file);
- // #endif
- // #ifdef MP-WEIXIN
- path = file.path;
- // #endif
- this.files.set(file.name,{file,path,name: file.name,size: file.size,progress: 0,type: 'waiting'});
-
- // #ifndef MP-WEIXIN
- this.onchange(this.files);
- this.instantly&&this.upload();
- // #endif
-
- // #ifdef MP-WEIXIN
- return true;
- // #endif
- }
- }
-
- /**
- * 移除文件
- * @param {string}name 不传name默认移除所有文件,传入name移除指定name的文件
- */
- clear(name='') {
- // #ifdef APP-PLUS
- this.dom&&this.dom.evalJS(`vm.clear('${name}')`);
- // #endif
-
- if (!name) {
- this.files.clear();
- }
- else {
- this.files.delete(name);
- }
- return this.onchange(this.files);
- }
-
- /**
- * 提示框
- * @param {string}msg 轻提示内容
- */
- toast(msg) {
- uni.showToast({
- title: msg,
- icon: 'none'
- });
- }
-
- /**
- * 微信小程序选择文件
- * @param {number}count 可选择文件数量
- */
- chooseMessageFile(type,count) {
- wx.chooseMessageFile({
- count: count,
- type: type,
- success: ({ tempFiles }) => {
- for (let file of tempFiles) {
- let next = this.addFile(file);
- if (!next) {return}
- }
- this.onchange(this.files);
- this.instantly&&this.upload();
- },
- fail: () => {
- this.toast(`打开失败`);
- }
- })
- }
-
- _overrideUrlLoading() {
- this.dom.overrideUrlLoading({ mode: 'reject' }, e => {
- let {retype,item,files,end} = this._getRequest(
- e.url
- );
- let _this = this;
- switch (retype) {
- case 'updateOption':
- this.dom.evalJS(`vm.setData('${JSON.stringify(_this.option)}')`);
- break
- case 'change':
- try {
- _this.files = new Map([..._this.files,...JSON.parse(unescape(files))]);
- } catch (e) {
- return console.error('出错了,请检查代码')
- }
- _this.onchange(_this.files);
- break
- case 'progress':
- try {
- item = JSON.parse(unescape(item));
- } catch (e) {
- return console.error('出错了,请检查代码')
- }
- _this._changeFilesItem(item,end);
- break
- default:
- break
- }
- })
- }
-
- _getRequest(url) {
- let theRequest = new Object()
- let index = url.indexOf('?')
- if (index != -1) {
- let str = url.substring(index + 1)
- let strs = str.split('&')
- for (let i = 0; i < strs.length; i++) {
- theRequest[strs[i].split('=')[0]] = unescape(strs[i].split('=')[1])
- }
- }
- return theRequest
- }
-
- _changeFilesItem(item,end=false) {
- this.debug&&console.log('onprogress',JSON.stringify(item));
- this.onprogress(item,end);
- this.files.set(item.name,item);
- }
-
- _uploadHandle(item) {
- item.type = 'loading';
- delete item.responseText;
- return new Promise((resolve,reject)=>{
- this.debug&&console.log('option',JSON.stringify(this.option));
- let {url,name,method='POST',header,formData} = this.option;
- let form = new FormData();
- for (let keys in formData) {
- form.append(keys, formData[keys])
- }
- form.append(name, item.file);
- let xmlRequest = new XMLHttpRequest();
- xmlRequest.open(method, url, true);
- for (let keys in header) {
- xmlRequest.setRequestHeader(keys, header[keys])
- }
-
- xmlRequest.upload.addEventListener(
- 'progress',
- event => {
- if (event.lengthComputable) {
- let progress = Math.ceil((event.loaded * 100) / event.total)
- if (progress <= 100) {
- item.progress = progress;
- this._changeFilesItem(item);
- }
- }
- },
- false
- );
-
- xmlRequest.ontimeout = () => {
- console.error('请求超时')
- item.type = 'fail';
- this._changeFilesItem(item,true);
- return resolve(false);
- }
-
- xmlRequest.onreadystatechange = ev => {
- if (xmlRequest.readyState == 4) {
- if (xmlRequest.status == 200) {
- this.debug&&console.log('上传完成:' + xmlRequest.responseText)
- item['responseText'] = xmlRequest.responseText;
- item.type = 'success';
- this._changeFilesItem(item,true);
- return resolve(true);
- } else if (xmlRequest.status == 0) {
- console.error('status = 0 :请检查请求头Content-Type与服务端是否匹配,服务端已正确开启跨域,并且nginx未拦截阻止请求')
- }
- console.error('--ERROR--:status = ' + xmlRequest.status)
- item.type = 'fail';
- this._changeFilesItem(item,true);
- return resolve(false);
- }
- }
- xmlRequest.send(form)
- });
- }
-
- _uploadHandleWX(item) {
- item.type = 'loading';
- delete item.responseText;
- return new Promise((resolve,reject)=>{
- this.debug&&console.log('option',JSON.stringify(this.option));
- let form = {filePath: item.file.path,...this.option };
- form['fail'] = ({ errMsg = '' }) => {
- console.error('--ERROR--:' + errMsg)
- item.type = 'fail';
- this._changeFilesItem(item,true);
- return resolve(false);
- }
- form['success'] = res => {
- if (res.statusCode == 200) {
- this.debug&&console.log('上传完成,微信端返回不一定是字符串,根据接口返回格式判断是否需要JSON.parse:' + res.data)
- item['responseText'] = res.data;
- item.type = 'success';
- this._changeFilesItem(item,true);
- return resolve(true);
- }
- item.type = 'fail';
- this._changeFilesItem(item,true);
- return resolve(false);
- }
-
- let xmlRequest = uni.uploadFile(form);
- xmlRequest.onProgressUpdate(({ progress = 0 }) => {
- if (progress <= 100) {
- item.progress = progress;
- this._changeFilesItem(item);
- }
- })
- });
- }
- }
|