前端vue+element实现导入导出的几种方式和封装

1. 文件导出

常用的文件导出方式有两种:

1.1 根据后端返回的url导出

请求后端接口,获取返回的url ,直接window.location.href = url;

1.2 后端返回文件流导出

后端返回文件流的处理,一般是获取流文件,然后创建a标签,添加href属性,再打开访问,项目用的多可以封装一个专门的导出请求,示例:

import axios from 'axios' 

const postDownload = function (url, params = {}, data = {}) { //定义postDownload方法
	return new Promise((resolve, reject) => {
		axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
		axios.post(url, params, {
   			params: data,
    		responseType: "blob"
 		 })
  		.then(response => {
	        let headers = response.headers;
	        let name = headers['content-disposition'];//这里如果没有获取到,联系后端设置一下headers
	        let filename = "";
	        let t = /filename="([^;]*);?"/i.exec(name);
	        null === t && (t = /filename=([^;]*);?/i.exec(name));
	        if (null !== t && t.length > 1) {
	          filename = decodeURIComponent(t[1]); //以上几步是为了获取传递过来的文件名,
	        }
	        let blob = new Blob([response.data], {  //ArrayBuffer转为Blob
	          type: "application/octet-stream"
	        });
	        let downloadElement = document.createElement('a');    //创建a标签
	        let href = window.URL.createObjectURL(blob);  		
	        downloadElement.href = href;						//设置href属性
	        downloadElement.download = filename; 				//设置文件名
	        document.body.appendChild(downloadElement);
	        downloadElement.click();
	        document.body.removeChild(downloadElement);
	        window.URL.revokeObjectURL(href);   				 //释放创建的URL对象
	        resolve(response.data);
 	 }, err => {
   	 		reject(err);
  		});
  	});
 }
 
 export{
 	postDownload
 }

2.文件导入

element ui + vue 的项目,使用el-upload组件,如果仅仅导入文件没有传参需求,通常action绑定上传地址即可,如果需要传递参数,则可绑定http-request自定义上传事件

自定义上传事件导入压缩包,并实时显示进度条实例(解析文件包内容的部分注释掉了,根据需要拿):

html部分:
<el-upload
    class="upload-demo"
    action      //   没有传参需求,此处可直接绑定地址
    accept=".zip,.tar"   //限制文件格式
    :show-file-list="false"
    :auto-upload="false"    //自动上传关闭
    ref="upload"
    :http-request="requestHandler"    //自定义上传事件
    :on-change="handleChange"     
    :on-exceed="exceedHanlder"   
  >
    <el-button type="primary" style="width: 200px"
      >任务导入安装包</el-button
    >
    <div>
      {{ fileName }}<i class="iconfont" v-if="isComplete">&#xe65a;</i>      //展示文件名,此处用了iconfont图标
    </div>
    <el-progress
      v-if="isPercentage"    //data中申明的变量,用于确定进度条的显示隐藏,默认false
      class="progress"
      :stroke-width="10"
      style="width: 100px"
      :percentage="percentage"
    ></el-progress>
  </el-upload>
  
  js部分:
  handleChange(file, fileList) {
  	 if (fileList.length > 1) {
    	 fileList.splice(0, 1);    						//保持上传的文件只有一个,点击按钮导入的时候替换之前的包
  	}
     this.fileName = file.name;
     this.isComplete = false;				//引入的icon图标是否展示,
     
     如果项目需要解析包里的内容,需要封装一个promise拿到reading.onload里解析的结果resolve出来
     直接全局定义变量然后赋值,在外部是拿不到这个结果的
     
  // return new Promise((resolve, reject) => {       
  //   let reader = new FileReader(); //先new 一个读文件的对象 FileReader
  //   if (typeof FileReader === "undefined") {
  //     //用来判断你的浏览器是否支持 FileReader
  //     this.$message({
  //       type: "info",
  //       message: "您的浏览器不支持文件读取。",
  //     });
  //     return;
  //   }
  //   //  reader.readAsText(file.raw, "gb2312");  //读.txt文件
  //   reader.readAsArrayBuffer(file.raw); //读任意文件
  //   reader.onload = function (e) {
  //     var ints = new Uint8Array(e.target.result); //要使用读取的内容,所以将读取内容转化成Uint8Array
  //     ints = ints.slice(0, 5000); //截取一段读取的内容
  //     let snippets = new TextDecoder("gb2312").decode(ints); //二进制缓存区内容转化成中文(即也就是读取到的内容)
  //     console.log("读取的内容如下:");
  //     console.log(snippets);
  //     resolve(snippets);
  //   };
  // }).then((res) => {
  //   console.log(res, "res");
  //   this.fileMessage = res;   
  // });
  },
  exceedHanlder(files, fileList) {
  	 this.$message({ type: "warning", message: "只能上传一个文件" });
  },
  requestHandler(param) {
      let params = new FormData();         	//自定义上传事件,FormData格式上传文件,顺便携带project_name参数
      params.append("file", param.file);
      params.append("project_name", this.taskImportForm.name);   
      const config = {
        onUploadProgress: (progressEvent) => {        //通过回调函数拿到上传文件的实时信息,进度条percentage赋值
          // progressEvent.loaded:已上传文件大小
          // progressEvent.total:被上传文件的总大小
          this.isPercentage = true;
          this.percentage = Number(
            ((progressEvent.loaded / progressEvent.total) * 100).toFixed(2)
          );
        },
      };
    //axios需要引入一下,这里没有封装请求的方法
  	axios.post("http://192.168.40.183:8000/api/files/upload_zip", params, config) 
    .then((res) => {
      if (res.data.code == 200) {
        this.isPercentage = false;
        this.isComplete = true;
        this.packageInfoList = res.data.data;
        this.$message({
          type: "success",
          message: "上传成功",
        });
      } else {
        this.$message.error("上传失败,请重新上传!");
      }
    });
  }

备注:el-updata组件要展示进度条,方便的做法是通过触发文件上传时on-progress钩子函数,拿到file已上传文件大小和总文件大小的数据,但是我发现项目里一直触发不了这个钩子函数,百度很多说是可能模拟数据引入了mock,但是项目并没有mock数据,暂时只能用请求回调中拿file信息,后面找到原因再补上。


版权声明:本文为weixin_50561602原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。