文件上传
vue中的文件上传主要分为两步:前台获取到文件和提交到后台
获取文件
前台获取文件,主要是采用input框来实现
<el-dialog :title="addName" :visible.sync="dialogAddFile" width="500px" style="padding:0;" @close="resetAdd">附件名称:<el-input v-model="addFileName" autocomplete="off" size="small" style="width: 300px;" ></el-input><div class="add-file-right" style="height:70px;margin-left:100px;margin-top:15px;"><div class="add-file-right-img" style="margin-left:70px;">上传文件:</div><input type="file" ref="clearFile" @change="getFile($event)" multiple="multiplt" class="add-file-right-input" style="margin-left:70px;" accept=".docx,.doc,.pdf"><span class="add-file-right-more">支持扩展名:.doc .docx .pdf </span></div><div class="add-file-list"><ul><li v-for="(item, index) in addArr" :key="index"><a >{{item.name}}</a></li></ul></div><div slot="footer" class="dialog-footer"><el-button type="primary" @click="submitAddFile" size="small">开始上传</el-button><el-button @click="resetAdd" size="small">全部删除</el-button></div></el-dialog>
最重要的是这一句代码:
通过file类型的input框实现文件上传;然后通过设置multiple="multiplt"实现了多文件上传,并且使用accept实现了上传文件类型限制;最后通过监听change事件,前台获取到上传的文件。
getFile(event){var file = event.target.files;for(var i = 0;i<file.length;i++){// 上传类型判断var imgName = file[i].name;var idx = imgName.lastIndexOf("."); if (idx != -1){var ext = imgName.substr(idx+1).toUpperCase(); ext = ext.toLowerCase( ); if (ext!='pdf' && ext!='doc' && ext!='docx'){}else{this.addArr.push(file[i]);} }else{}}},
通过change事件中的event.target.files就能获取到上传的文件了,在上面再次对获取的文件进行了类型限制。
数据提交
获取到文件数据后,就需要将数据提交到后台,这里可以采用FormData的方式提交。
submitAddFile(){if(0 == this.addArr.length){this.$message({type: 'info',message: '请选择要上传的文件'});return;}var formData = new FormData();formData.append('num', this.addType);formData.append('linkId',this.addId);formData.append('rfilename',this.addFileName);for(var i=0;i<this.addArr.length;i++){formData.append('fileUpload',this.addArr[i]);}let config = {headers: {'Content-Type': 'multipart/form-data','Authorization': this.token}};this.axios.post(apidate.uploadEnclosure,formData,config).then((response) => {if(response.data.info=="success"){this.$message({type: 'success',message: '附件上传成功!'});}})}
在进行数据提交的时候,有两点需要注意:formData对象和Content-Type,处理好着两点以后,就和其他的接口一样了。
文件下载
首先是从服务器获取文件列表,并展示:
<div class="about-file"><div class="about-file-title">相关材料</div><ul><li v-for="(item, index) in tenEnclosure.rows" :key="index"><a target="_self" >{{item.tenPencSourname}}</a><span @click="toxiazai(index,4,item.tenureId)" title="下载"></span><span @click="toshanchu(index,4,item.tenureId)" title="删除"></span></li></ul> </div>
然后完成点击下载事件:
toxiazai(index,num,id){var tempForm = document.createElement("form");//创建form表单,以下数form表单的各种参数tempForm.id = "tempForm1";tempForm.method = "post";tempForm.action = apidate.downloadEnclosure;tempForm.target="_";var hideInput1 = document.createElement("input");hideInput1.setAttribute('type','hidden');hideInput1.setAttribute('name','linkId');hideInput1.setAttribute('id','linkId');hideInput1.setAttribute('value',id);tempForm.appendChild(hideInput1);var hideInput2 = document.createElement("input");hideInput2.setAttribute('type','hidden');hideInput2.setAttribute('name','num');hideInput2.setAttribute('id','num');hideInput2.setAttribute('value',num);tempForm.appendChild(hideInput2);if(document.all){tempForm.attachEvent("onsubmit",function(){}); //IE}else{var subObj = tempForm.addEventListener("submit",function(){},false); //firefox}document.body.appendChild(tempForm);if(document.all){tempForm.fireEvent("onsubmit");}else{tempForm.dispatchEvent(new Event("submit"));}tempForm.submit();//提交POST请求document.body.removeChild(tempForm);
},
文件在线打开
在PC端,有很多文件都试采用下载的方式,但是在手机端,更多的是直接在线打开。如果要实现文件的在线打开,可以借助于a标签的href属性实现
<ul><li v-for="(item,index) in noticeList" v-bind:key="index" class="person-list" @click="notice(index)"><div class="person-list-name"><a v-bind:href="[filePrefix+item.uuid_name]">{{item.file_name}}</a></div><div class="person-list-time">上传时间:{{item.create_time}}</div></li> </ul>
因为使用这种方式进行文件打开的时候,需要有完整的路径名称,但是在从后台获取到列表的时候,通常是相对路径,所以需要进行路径拼接: v-bind:href="[filePrefix+item.uuid_name]"
图片上传和预览
通过在上传文件以后,就可以拿到文件的名称进行展示。但是如果是用这种方式进行图片上传,展示不再是图片名称了,而应该是图片展示。
例如,要实现上面这种效果,使用input进行图片上传
<div class="list-img"><ul><li v-for="(item,index) in imgArr" :key="index"><img :src="item.path" alt="" ><a @click="todel(index)"></a></li><li><div class="addImg" v-if="imgArr.length<3"><span class="add">上传图片</span><span class="add">(最多上传3张)</span><input type="file" @change="getFile($event)" accept=".jpg,.png,.bmp,.gif"></div></li></ul></div>
getFile(event){var file = event.target.files;for(var i = 0;i<file.length;i++){// 上传类型判断var imgName = file[i].name;var idx = imgName.lastIndexOf("."); if (idx != -1){var ext = imgName.substr(idx+1).toUpperCase(); ext = ext.toLowerCase( ); if (ext!='jpg' && ext!='png' && ext!='bmp' && ext!='gif'){}else{this.imgArr.push(file[i]);} }else{}}},
因为在打印event对象的时候,发现上传的图片中包含一个path字段,对应的就是图片在设备上地址,就想当然的以为可以用这种方式展示图片,结果很显然的报错了,在网上查了一下才知道,要展示使用input上传的图片,需要使用FileReader。
具体的就是,input获取到的图片,是不能立即展示的,两者根本不是一回事,所以,还需要一个数组,用来存放展示的图片。
getFile(event){var file = event.target.files;let that = this;for(var i = 0;i<file.length;i++){// 上传类型判断var imgName = file[i].name;var idx = imgName.lastIndexOf("."); if (idx != -1){var ext = imgName.substr(idx+1).toUpperCase(); ext = ext.toLowerCase( ); if (ext!='jpg' && ext!='png' && ext!='bmp' && ext!='gif'){}else{that.imgArr.push(file[i]);} }else{ }//展示上传的图片let reader = new FileReader()reader.readAsDataURL(file[i])reader.onload = function(e) {that.imgShow.push(this.result);}}},
这样,提交数据的时候,使用的是imgArr,而展示的时候,使用的是imgShow
还有一点需要注意的是,这里还有一个删除操作,这里的删除,不仅是在界面上的不可见,更是代表删除的这种照片,不需要传递到后台,因此,两个数组都需要进行删除