input 文件上传
<button class="blueButton fileinput-button" style="width:165px;" @click="importExcel_1"> <input type="file" ref="importFile1"> 导入录播、中控数据 </button>
importExcel_1(){ let finput = this.$refs.importFile1; finput.onchange = (() => { if (finput.value.match(/\.(xls|xlsx|xlsm)(\?.*)?$/)) { this.templateObj.excel1.fileName = this.setExcelName(finput.files[0].name); this.templateObj.excel1.file = finput.files[0]; } else { new FailHint().show('请选择正确的Excel格式文件!'); } }); }
js方法:
文件断点续传: 弹框: <Modal v-model="uploadWinFlag" :mask-closable="false" @on-cancel="cancelUpload()"> <p slot="header"> <span>上传</span> </p> <div class="videoBody"> <Form ref="loadForm" style="padding-right: 40px;" :rules="ruleUpload" :model="currentUpload" :label-width="80"> <Form-item label="资源名称" prop="resourcename"> <Input v-model="currentUpload.resourcename"></Input> </Form-item> <Form-item style="position: relative;" label="作者" prop="userid"> <Select :loading="status.loading" placeholder="请输入教师姓名" remote :remote-method="searchTeacher" class="customInput" v-model="currentUpload.userid" clearable filterable> <Option-group v-for="it in teacherList" :label="it.title" :key="it.id"> <Option v-for="tea in it.teachers" :value="tea.id" :label="tea.name" :key="tea"></Option> </Option-group> </Select> </Form-item> <Form-item label="所属教室"> <tree-select class="custom-input" style="width: 2.6rem;" v-model="currentUpload.areaid" :data="treeList" nameprops="title"></tree-select> </Form-item> <div style="padding-left: 15px;"> <button class="modalBtn blueButton fileinput-button" @click="pickVideo()" style="width:80px;"> <input type="file" ref="videoInput" multiple="true"> 选择文件 </button> </div> <ul class="loadedVideoCls"> <li v-for="(it,index) in currentUpload.list" :title="it.showName" > <span style="margin-right: 10px;text-overflow:ellipsis;white-space: nowrap;overflow: hidden;">{{it.showName}}</span> <i style="cursor: pointer;position: relative;" class="ivu-icon ivu-icon-close" @click="removeLoaded(index)" ></i> </li> </ul> </Form> </div> <div> <ul class="loadingVideoCls"> <li v-for="(it,index) in uploadingVideos" v-show="!it.complete"> <div>{{it.name}}</div> <div class="progressCls"> <div> <div style="background: #1FB529;width: 33px;height: 100%;" :style="{width:it.percentLoaded+'%'}"></div> </div> <span class="percentNum" >{{it.percentLoaded}}%</span> <i :style="{visibility:it.complete?'hidden':'visible'}" class="ivu-icon ivu-icon-close-circled progressClose" @click="removeLoading(index)"></i> </div> <div> <div>速度:{{it.bytesSpeed}}M/s</div> <div>已上传:{{it.bytesLoaded}}M/{{it.bytesTotal}}M</div> <div>剩余时间:{{it.remainTime}}s</div> </div> </li> </ul> </div> <div slot="footer"> <button class="buttonCls modalBtn" @click="cancelUpload()">取消</button> <button class="modalBtn blueButton" @click="valiadateUpload('loadForm')"> 保存 </button> </div> </Modal>
removeLoaded(index){ console.log('------------>>>deleteloaded',index); this.currentUpload.list.splice(index,1); this.uploadingVideos.splice(index,1); let finput = this.$refs.videoInput; finput.value = ''; }, removeLoading(index){ console.log('----------deleteloading',index); this.uploadedUtil.deleteLoading(index); }, pickVideo(){ let finput = this.$refs.videoInput; finput.value == ""; finput.onchange = this.finputChange; }, finputChange(){ let finput = this.$refs.videoInput; if (finput.value.match(/\.(MP4|mp4)(\?.*)?$/)) { let len = finput.files.length; for (let i = 0; i < len; i++) { let f = finput.files[i]; console.log('===========>obj=',this.currentUploadObj) if (this.currentUploadObj.hasOwnProperty(f.name)) { util.arrayAdd(this.currentUpload.list,this.currentUploadObj[f.name],'showName') // this.currentUpload.list.push(this.currentUploadObj[f.name]); continue; } this.uploadingVideoFiles.push(f); this.uploadingVideos.push({name:f.name,bytesLoaded: '-', bytesTotal: '-', bytesSpeed: '-', remainTime: '-', percentLoaded: 0, complete: false}) } if (!this.uploadedUtil) { this.uploadedUtil = new uploadUtilBatch( this.uploadingVideoFiles, // 需要上传的文件列表 baseURL + 'tk', // 获取token的url baseURL + "zonekeyresource/uploadVedio", // 下载文件的url {areaid:this.currentUpload.areaid}, // post需要传的参数 // 上传进度 (progressInfo) => { console.log('----progress=>', progressInfo) let video = this.uploadingVideos[progressInfo.videoIndex]; if (!video) return; video.bytesLoaded = Math.round(progressInfo.bytesLoaded/1048576); video.bytesTotal = Math.round(progressInfo.bytesTotal/1048576); video.bytesSpeed = Math.round(progressInfo.bytesSpeed/1048576); video.remainTime = Math.max(0,progressInfo.remainTime); video.percentLoaded = progressInfo.percentLoaded; }, // 文件上传完成回调 (index,info) => { let video = this.uploadingVideos[index]; video['complete'] = true; let fileBean = info.fileBean; let infoObj = {name:fileBean.name,size:fileBean.size,resourcePath:fileBean.fileurl,showName:info.showName}; this.currentUploadObj[info.showName] = infoObj; this.currentUpload.list.push(infoObj); this.currentUpload.floder = info.floder; console.log('----complete=>', index); },(index) =>{ finput.value = ''; this.uploadingVideos.splice(index,1); finput.value == ""; }); this.uploadedUtil.start(); }else this.uploadedUtil.resumeUpload(); } else { new FailHint().show('请选择正确的视频格式文件!'); } }, valiadateUpload(name){ this.$refs[name].validate((valid) => { if (valid) { this.uploadFile(); } }) }, uploadFile(){ videoServer.saveZonekeyResource(this.currentUpload).then(res=>{ if (res.id=='0') { new SuccessHint().show("已保存!"); this.cancelUpload(); this.selectItem = this.treeList[0]; this.firstNodeId = this.selectItem.id; this.selectItem['open'] = true; this.getVideoList(); } else new FailHint().show("保存失败!"); }); // this.uploadingVideoFiles = []; // this.uploadingVideos = []; }, // 取消上传 cancelUpload(){ this.currentUploadObj = {}; this.uploadingVideoFiles = []; this.uploadingVideos = []; this.uploadWinFlag = false; this.uploadedUtil = null; this.currentUpload = {areaid:'',userid:'',resourcename:'',list:[]}; }, util: /** * Created by ZHX on 2017/6/12. */ import * as util from './Util' function UploadUtilBatch(files, tokenUrl, postUrl, params, progressFun, endFun, delBack) { this.tokenUrl = tokenUrl; this.postUrl = postUrl; this.initPostUrl = postUrl; this.params = params; this.files = files; this.progressFun = progressFun; this.endFun = endFun; this.delBack = delBack; } UploadUtilBatch.prototype = { tokenUrl: "", initPostUrl:'', postUrl: "", files: [], progressFun: "", endFun: "", // 块大小 10M. filePiece: 10485760, // 正在下载的文件 currentFile: null, // 正在下载的文件索引 cfIndex: 0, xhrHandler: "", XHR: "", params: {}, // 记录每次开始位置 bytesStart: 0, floder: '', FileBean: null, // 下载中 loading: false, start(){ this.floder = ''; if (util.isArray(this.files) && this.files.length > 0) { this.upload(this.files[this.cfIndex]); } else new Error("穿入文件列表为空!"); }, upload (f) { this.loading = true; this.currentFile = f; this.FileBean = null; console.log('===========currentFile', f); /** request the server to figure out what's the token for the file: */ let xhr = new XMLHttpRequest; let vars = { name: this.currentFile['name'], size: this.currentFile['size'], }; let tokenUrl = fAddVars(vars, this.tokenUrl) + "&" + util.fGetRandom(); xhr.open("GET", tokenUrl, !0); xhr.onreadystatechange = () => { if (xhr.readyState != 4 || xhr.status < 200) return false; try { let token = JSON.parse(xhr.responseText).token; this.initFile({token, size: this.currentFile.size, name: this.currentFile.name}) } catch (e) { console.log(e); } } xhr.send(); }, initFile(params){ let xhr = new XMLHttpRequest; let initUrl = fAddVars(params, this.initPostUrl) + "&" + util.fGetRandom(); xhr.open("GET", initUrl, !0); xhr.onreadystatechange = () => { if (xhr.readyState != 4 || xhr.status < 200) return false; try { let res = JSON.parse(xhr.responseText); this.postUrl = fAddVars( fMergeJson(params, this.params), this.initPostUrl); this.uploadFile(res.hasOwnProperty('start')?Number(res.start):0); } catch (e) { console.log(e); } } xhr.send(); }, uploadFile(pos){ this.XHR = new XMLHttpRequest; this.bytesStart = pos; let _xhr = this.XHR, upload = _xhr.upload; this.xhrHandler = fExtend(this.loadHandler, this); upload.addEventListener("progress", this.xhrHandler, !1); _xhr.addEventListener("load", this.xhrHandler, !1); _xhr.addEventListener("loadend", this.xhrHandler, !1); _xhr.onreadystatechange = () => { if (_xhr.readyState != 4 || _xhr.status < 200) return false; try { let data = JSON.parse(_xhr.responseText); (data.hasOwnProperty('zonekeyResource')) && (this.floder = data.zonekeyResource.floder); (data.hasOwnProperty('FileBean')) && (this.FileBean = data.FileBean); } catch (e) { console.log(e); } } let blob = this.sliceFile(this.currentFile, pos, pos + this.filePiece); let range = "bytes " + pos + "-" + (pos + blob.size) + "/" + this.currentFile.size; let purl = this.floder ? (this.postUrl + '&floder=' + this.floder) : this.postUrl; _xhr.open("POST", purl, !0); _xhr.setRequestHeader("Content-Range", range); _xhr.setRequestHeader("Content-type", "application/x-www-four-urlencoded"); _xhr.send(blob); }, loadHandler(event){ let xhr = this.XHR; switch (event.type) { case "load": console.log("load"); let uploaded = 0; let respJson = null; let bError = !1; try { if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 308)) { uploaded = (respJson = eval("(" + xhr.responseText + ")")) ? respJson.start : -1; } else if (xhr.status < 500 && xhr.status >= 400) { bError = !0; } else if (xhr.status < 200) { return; } /** the response can't process the request, so throws out the error. */ bError = bError || respJson.success == false; } catch (e) { bError = this.retriedTimes > 2; if (!bError) { // this.retry(); return; } } //check whether upload complete yet if (uploaded < this.currentFile.size - 1) { this.retriedTimes = 0; this.uploadFile(uploaded); } else { this.endFun(this.cfIndex, {floder: this.floder, fileBean: this.FileBean, showName: this.currentFile.name}); let files = this.files; if (files.length - 1 > this.cfIndex) this.upload(files[++this.cfIndex]); else this.loading = false; } break; case "loaded": console.log("loaded"); break; case "progress": { // console.log('------------->progressBack',event) let total = this.currentFile.size, loaded = this.bytesStart + event.loaded, now = Date.now(), cost = (now - this.preTime) / 1E3, totalSpeeds = 0; if (0.68 <= cost || 0 === this.bytesSpeeds.length) { this.bytesPrevLoaded = Math.max(this.bytesStart, this.bytesPrevLoaded); this.bytesSpeed = Math.round((loaded - this.bytesPrevLoaded) / cost); this.bytesPrevLoaded = loaded; this.preTime = now; 5 < this.bytesSpeeds.length && this.bytesSpeeds.shift(); 5 > this.bytesSpeeds.length && (this.bytesSpeed = this.bytesSpeed / 2); this.bytesSpeeds.push(this.bytesSpeed); for (let i = 0; i < this.bytesSpeeds.length; i++) totalSpeeds += this.bytesSpeeds[i]; this.bytesSpeed = Math.round(totalSpeeds / this.bytesSpeeds.length); this.remainTime = Math.ceil((total - loaded) / this.bytesSpeed); } this.progressFun({ videoIndex: this.cfIndex, originEvent: event, bytesLoaded: loaded, bytesTotal: total, bytesSpeed: this.bytesSpeed, remainTime: this.remainTime, percentLoaded: Math.min(100, Math.floor(1E4 * loaded / total) / 100) }); } break; } }, deleteLoading(index){ this.files.splice(index, 1); if (index == this.cfIndex) { this.cancelUpload(); this.delBack(index); if (this.files.length - 1 > this.cfIndex) this.upload(this.files[this.cfIndex]); else this.cfIndex = this.files.length - 1; } else this.delBack(index); }, // 继续下载 resumeUpload(){ // 如果当前不在下载状态 if (!this.loading) { console.log('---------->total',this.files.length,this.cfIndex); if (this.files.length - 1 > this.cfIndex) this.upload(this.files[++this.cfIndex]); } }, cancelUpload() { this.XHR && (this.XHR.abort(), this.resetXhr()); this.loading = false; }, resetXhr(){ if (this.XHR) { try { this.XHR.upload.removeEventListener("progress", this.xhrHandler) this.XHR.removeEventListener("loadend", this.xhrHandler) this.XHR.removeEventListener("load", this.xhrHandler) } catch (e) { throw e; } this.XHR = null; } }, bytesPrevLoaded: 0, bytesSpeeds: [], bytesStart: 0, preTime: 0, sliceFile(f, startPos, endPos) { startPos = startPos || 0; endPos = endPos || 0; return f.slice ? f.slice(startPos, endPos) : f.webkitSlice ? f.webkitSlice(startPos, endPos) : f.mozSlice ? f.mozSlice(startPos, endPos) : f; }, removeFile(){ } }; function fExtend(a, b) { var c = 2 < arguments.length ? [arguments[2]] : null; return function () { var d = "string" === typeof a ? b[a] : a, e = c ? [arguments[0]].concat(c) : arguments; return d.apply(b || d, e); }; } function fAddVars(json, url, c) { var _array = [], _sep = "&", f = function (json, c) { var e = url ? /\[\]$/.test(url) ? url : url + "[" + c + "]" : c; "undefined" != e && "undefined" != c && _array.push("object" === typeof json ? fAddVars(json, e, !0) : "[object Function]" === Object.prototype.toString.call(json) ? encodeURI(e) + "=" + encodeURI(json()) : encodeURI(e) + "=" + encodeURI(json)) }; if (!c && url) _sep = /\?/.test(url) ? /\?$/.test(url) ? "" : "&" : "?", _array.push(url), _array.push(fAddVars(json)); else if ("[object Array]" === Object.prototype.toString.call(json) && "undefined" != typeof json) for (var g = 0, c = json.length; g < c; ++g) f(json[g], g); else if ("undefined" != typeof json && null !== json && "object" === typeof json) for (g in json) f(json[g], g); else _array.push(encodeURI(url) + "=" + encodeURI(json)); return _array.join(_sep).replace(/^&/, "").replace(/%20/g, "+") } function fMergeJson(base, extend) { var result = {}; for (var attr in base) result[attr] = base[attr]; for (var attr in extend) result[attr] = extend[attr]; return result; } export default UploadUtilBatch;