文件上传
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=" 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
还有一点需要注意的是,这里还有一个删除操作,这里的删除,不仅是在界面上的不可见,更是代表删除的这种照片,不需要传递到后台,因此,两个数组都需要进行删除