0


前端文件下载方式总结

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

1、form 表单下载

1.1、表单下载基本使用

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

function formDownload(data){ // data :<object> 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 :<object> 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 再通过连接下载。

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

标签: html5 javascript

本文转载自: https://blog.csdn.net/m0_67793437/article/details/139778587
版权归原作者 Wu Youlu 所有, 如有侵权,请联系我们删除。

“前端文件下载方式总结”的评论:

还没有评论