阅读 35

前端的三种下载方法

上传和下载是前端er们经常遇到的场景,上传还可以用element、iview等各种封装好的组件,下载则不然,常常需要写很多的代码,而且经常跟后端对接失败,有时候真是心里mmp。好了,接下来分享一下自己经常使用的3种下载方式,有需要的同学请自取,自己也相当于做个整理回顾。

  1. window.open的方式

    此种方式最low,然而却是最省事的,因此经常被某些爱省事的后端拿来就用。

    使用方式:window.open(url),url既可以是绝对路径,也可以是相对路径。需要注意的是,拼接的链接一定要是合法的url,我在很长的一段时间里不知道如何正确地拼接数组参数的url,实在是惭愧,直到后来了解到有encodeURIComponent这个神器…

    缺点:新打开页面,影响交互体验;直接下载,不能自定义文件名,文件存放位置

      //导出列表
      exportList(obj) {
        let link =
          window.globalConfig.defaultProxyPath +
          url +
          "/key/person/export?idNums=" +
          encodeURIComponent(JSON.stringify(obj));
        window.open(link);
      },
    复制代码
  2. 虚拟表单的方式

    表单的下载历史可谓源远流长,下文中的jq调用方式,原理没变,同样是生成虚拟表单,然后模拟提交事件,然后销毁虚拟表单。但是都9102年了还用这种方式来下载,不可谓不low。

    缺点:过时

        //生成虚拟表单,然后手动触发提交事件
    	downLoadFile(options) {
          //let $ = $.noConflict();
          let config = $.extend(
            true,
            {
              method: "post"
            },
            options
          );
          let tmpIframe = $('<iframe id="down-file-iframe" />');
          let tmpForm = $(
            '<form target="down-file-iframe" method=" ' + config.method + '" />'
          );
          tmpForm.attr("action", config.url);
          for (let key in config.data) {
            tmpForm.append(
              '<input type="hidden" name="' +
                key +
                '" value="' +
                config.data[key] +
                '" />'
            );
          }
          tmpIframe.append(tmpForm);
          $(document.body).append(tmpIframe);
          tmpForm[0].submit();
          tmpIframe.remove();
        }
    
    	//调用
    	 this.downLoadFile({
             url: predix + `/rs/namelist/blackreport`,
             data: param
         });
    
    复制代码
  3. 文件流式下载

    H5其实提供了很多很好用的api,流文件下载就是其中一种。在向后端发送请求时,我们只需要将header中的content-type设置成我们想要的格式,便能得到想要的流文件,从而触发浏览器的下载功能。

    优点:简洁,绿色,可自定义文件名和文件存放位置

    注意:此方法并不是万无一失,关于header的设置需要前后端对接清楚,在某些情况下,比如跨域,headers的某些属性将会受限,需要后端要较高的素养

        //发出请求
    	download(url, param) {
          let resType;
          if (window.navigator.msSaveOrOpenBlob) {
            // for IE
            resType = "arraybuffer";
          } else {
            resType = "blob";
          }
          return axios({
            url: url,
            method: "post",
            responseType: resType,
            headers: { Accept: "application/octet-stream" },
            data: param
          });
        },
    	//得到文件
        real_download(obj) {
          this.download("/rs/experiment/graph/export", obj).then(res => {
            let blobObject = new Blob([res.data]);
            // 获取文件名
            let disposition = res.headers["content-disposition"]
              ? res.headers["content-disposition"]
              : "";
            let filename = decodeURI(disposition.split("filename=")[1]);
            // let filename = row.fileName;
    
            if (window.navigator.msSaveOrOpenBlob) {
              // for IE
              window.navigator.msSaveOrOpenBlob(blobObject, filename);
            } else {
              const file = window.URL.createObjectURL(blobObject);
              const link = document.createElement("a");
              document.body.appendChild(link);
              link.setAttribute("download", filename);
              link.setAttribute("href", file);
              link.click();
              //URL对象释放内存
              window.URL.revokeObjectURL(file);
              link.remove();
            }
          });
        },
    
    复制代码

    总结:简单说了下3种方式,主要还是自己做个记录,不爱查资料,全凭自己理解,错漏之处还望大家海涵。

关注下面的标签,发现更多相似文章
评论