前端文件下载方式总结

07-21 1158阅读

写在前面:网上关于前端实现文件下载的文章已经有很多了,而且有的写的十分详细专业。之前一直不愿意做此类记录,一来是觉得这方面的文章太多太详细了,没有写的必要;二来是想着自己写的还不一定有别人写的好。但随着日常开发中用到的文件下载功能用的越多,各种下载方式都有使用过,觉得需要记录一下,以方便使用。

前端文件下载方式总结
(图片来源网络,侵删)

1、form 表单下载

1.1、表单下载基本使用

form 表单下载是比较传统的下载方式,话不多说,直接看实例:

function formDownload(data){ // data : form 表单的传参 
    let form = document.createElement('form');
    form.id = 'idForm';
    form.name = 'name_form';
    form.style.display = 'none';
    document.body.appendChild(form);
    for (let i in data) {
      if (i !== 'action') {
        let input = document.createElement('input'); //创建 input 标签并传入 form 中,作为 form 的表单的发送参数
        input.type = 'text';
        input.name = i;
        input.value = data[i];
        form.appendChild(input);
      } else {
        continue;
      }
    }
    form.method = 'get';
    form.action = URL; // form 表单发送的地址
    form.submit();
    document.body.removeChild(form);
}
  • 表单的提交就相当于一次请求,input 中的值相当于传参
  • form 上有一个属性 target,这个属性指定返回结果放的位置,默认 _self 表示本页面
  • 浏览器可以识别的文件不能下载:txt、png、jpg、gif等
  • 无法获取下载进度
  • 可以避免URL过长问题

    1.2、 表单下载通过 iframe 接收返回信息并实现无刷新

    将 form.target 设置成 iframe ,可以获取返回的信息,完整代码:

    function formDownload(data) { // data : form 表单的传参 
        var target = 'sub_frame' + Date.parse(new Date());
        var iframe = document.createElement('iframe');
        iframe.src = window.location.href;
        iframe.name = target;
        iframe.id = target;
        iframe.width = 0;
        iframe.height = 0;
        iframe.style.display = 'none'
        document.body.appendChild(iframe);
        let form = document.createElement('form');
        form.id = 'idForm';
        form.name = 'name_form';
        form.setAttribute("target", target);
        form.style.display = 'none';
        document.body.appendChild(form);
        for (let i in data) {
            if (i !== 'action') {
                let input = document.createElement('input'); //创建 input 标签并传入 form 中,作为 form 的表单的发送参数
                input.type = 'text';
                input.name = i;
                input.value = data[i];
                form.appendChild(input);
            } else {
                continue;
            }
        }
        form.method = 'get';
        form.action = URL; // form 表单发送的地址
        form.submit();
        document.body.removeChild(form);
        // 通过循环去拿返回数据
        var count = 0;
        var timer = setInterval(function () {
            var iframeObj = $(window.frames[target].document);
            var val = iframeObj.find("pre").text();
            count++;
            if (count >= 60) {
                window.clearInterval(timer);
                document.body.removeChild(iframe);
                return false
            }
            if (val) {
                var res = JSON.parse(val);
                window.clearInterval(timer);
                document.body.removeChild(iframe);
            }
        }, 1000)
    }

    2、直接跳转下载

    2.1、location.href

    window.location.href = url;

     2.2、window.open

    window.open(url);
    •  以上两种适合 get 请求的单文件下载
    • 会出现 url 过长的问题,需要注意 url 编码
    • 浏览器可以识别的文件不能下载:txt、png、jpg、gif等

      3、a链接下载

          let a = document.createElement('a'); 
          a.style = 'display: none';
          a.download = filename;
          a.href = url;
          document.body.appendChild(a);
          a.click(); // 触发a标签的click事件
          document.body.removeChild(a);

      这种方式也无法解决浏览器可识别文件直接打开的问题,但是 HTML5 新属性 download 属性会解决这个问题。

      但是也会有局限:部分情况下会出现跨域问题,此时还是浏览器预览而非下载,download属性失效。可以用这个方法试一下文本、图片。

      部分浏览器由于兼容性问题(一般不会出现):

      const isSupport = 'download' in document.createElement('a');

      看支不支持 download 属性

       4、文件流下载之 blob + a 链接 + blob URL

                  let xhr = new XMLHttpRequest();
                  xhr.open('GET', videoUrl, true);
                  xhr.responseType = 'blob';
          
                  xhr.onload = function() {
                      if (xhr.status === 200) {
                          // 将视频Blob对象创建一个临时URL
                          let videoBlob = xhr.response;
                          let url = window.URL.createObjectURL(videoBlob);
                          // 设置a标签的属性,并触发点击事件进行下载
                          a.href = url;
                          a.download = fileName; //文件名
                          a.click();
                          // 释放URL对象
                          window.URL.revokeObjectURL(url);
                          a.remove()
                      }
                  };
                  xhr.send();

      发送 http 请求,指定返回值类型是 blob 流

      建议加上 download 的后缀名,避免极个别浏览器无法识别

      这种实现本质是通过 blob URL方式

      可通过 xhr.getResponseHeader("Content-Disposition") 获取 header 上的 Content-Disposition 属性,通过截取得到文件名

      5、 文件流下载之 blob + a 链接 + readAsDataURL

                  let xhr = new XMLHttpRequest();
                  xhr.open('GET', videoUrl, true);
                  xhr.responseType = 'blob';
          
                  xhr.onload = function() {
                      if (xhr.status === 200) {
                          // 将视频Blob对象创建一个临时URL
                          let videoBlob = xhr.response;
                          const fileReader = new FileReader();
                          fileReader.readAsDataURL(videoBlob);
                          fileReader.onload = function () {
                              const a = document.createElement('a');
                              a.style.display = 'none';
                              // 结果本质上是 base64 编码的 data URL 格式
                              a.href = fileReader.result;
                              a.download = name;
                              document.body.appendChild(a);
                              a.click();
                              document.body.removeChild(a);
                          }
                          
                      }
                  };
                  xhr.send();
      

      这个方法和上个 方法都是获取 blob 形式的返回值,只是结果处理方式不同,这种方式是通过 readAsDataURL  生成 base64 编码的 Data URL 再通过连接下载。

      两种方法都可以解决 浏览器直接打开无法下载的问题

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]