vue 上传文件和下载文件

Posted 今天你码 了吗

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue 上传文件和下载文件相关的知识,希望对你有一定的参考价值。

vue 上传文件和下载文件

1. 上传文件

上传文件我所使用的组件是element ui 的 el-upload,我一共进行了如下两步,第一步:修改样式,因为el-upload的样式不是我所要的,我想要这种的

代码如下

 <el-form-item label="导入文件:">
                <el-input v-model="filename"  placeholder="请选择文件" style="width: 190px"></el-input>
                <el-upload
                  class="upload-demo"
                  action="https://jsonplaceholder.typicode.com/posts/"
                  :on-change="handleChange"
                  :show-file-list="false"
                >
                  <el-button size="small" type="primary">点击上传</el-button>
                </el-upload>
              </el-form-item>

这里定义一个输入框,一个上传功能,一个按钮button 谁知el-upload为inline-block格式就可以在一行显示了 然后调整宽度就行了。
点击上传按钮 出来文件选项 选中后显示在input上 所以用到了on-change事件

handleChange(file) 
      this.filename = file.name
      this.agentForm.file = file.raw
    

这里的 this.filename就是显示的名字 file.raw是我们要上传的二进制文件他的格式是这样的

file类型的文件 我们需要转为formData格式,调用接口传给后端,

接口也需要加个样式

headers: 'Content-Type': 'multipart/form-data' ,`
加上这句,然后提交的时候代码如下

let fd = new FormData()
      // fd.append("file",this.agentForm.file )
      for(let i in this.agentForm) 
         fd.append(i, this.agentForm[i])
      

如果不仅仅传文件 还需要其他的 可以用for循环append到fd里面,然后调用接口 将fd传进去就好了。

2. 下载文件

直接贴代码把 直接就是button按钮点击 调用接口

 async downloadImportTemp() 
      const res = await downloadImportTemp()
      console.log(res)
      let blob = new Blob([res.data], type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" )
      let url = window.URL.createObjectURL(blob)
       let link = document.createElement('a')
       link.style.display = 'none'
      //  console.log(name[1])
       link.download =  "认证代理导入模板.xlsx"
       link.href = url
       link.click()
      // console.log(url)
      // this.url = url
    ,

整个步骤为 点击按钮调用接口得到文件,接口也要加上一句

responseType: 'blob',

但是后端需要Blob格式的,所以new Blob将得到的数据放进去,同时指定下载的type 根据不同的后缀 选择不同的type 这里是xlsx格式的 不知道type的可以点击这个连接
下载链接: blob类型大全
最重要的是后面的跳转环节 我刚开始是自己设置了一个a标签,然后将url地址改为下载地址 但是出现了很多问题,一个是点击有时候会跳转,一个是点击有时候第一次不管用。我们不自己create一个a 然后按照代码的步骤就可以很好的解决以上问题。a标签的download属性 可以设置下载的文件名字 可以自己设置,大致就这些 有问题欢迎一起讨论学习。

vue中的文件上传和下载

目录

文件上传

获取文件

数据提交

文件下载

文件在线打开

图片上传和预览


文件上传

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

还有一点需要注意的是,这里还有一个删除操作,这里的删除,不仅是在界面上的不可见,更是代表删除的这种照片,不需要传递到后台,因此,两个数组都需要进行删除

以上是关于vue 上传文件和下载文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 vue js 和 axios 上传多个文件

Vue.js - 元素UI - 上传文件添加参数

Vue.js使用Blob的方式实现excel表格的下载(流文件下载)

如何使用 Vue.Js 上传仅图像文件?

vue、JS图片url转base64

在vue.js中上传照片和其他表单内容一起使用。