JavaScript不同场景下的文件下载方案详解

 更新时间:2023年12月27日 09:10:12   作者:云小遥  
这篇文章主要为大家详细介绍了JavaScript中不同场景下的三种常见文件下载方案,文中的示例代码讲解详细,有需要的小伙伴可以参考一下

文件下载实践方案汇总

前端开发中 常用 到的下载方式:

  • a标签下载(链接下载)
  • fetch / axios / XMLHttpRequest 异步请求资源下载
  • blob 下载
  • FileSaver 第三方库下载

除了以上几种通用性方案,在JQuery时期还会经常使用到 form 表单提交等方式,但是随着Vue、React的兴起,一般在进行选型时便很少使用form表单提交的形式了。

方案1:a标签下载

简单下载方式,通过a标签的href属性加载下载url,适合普通场景下的简单下载。

适合场景

  • get 请求
  • 返回为文件流 / 返回URL

不适合场景

  • 下载需要计算、权限验证、携带Cookie
  • 需要动态生成文件内容,即需要Post传参
  • 需要处理跨域问题
  • 需要处理大文件下载(10M以上)
  • 需要断点续传或文件下载进度监控等

应用示例

  <a 
     href="https://images.unsplash.com/photo-1682687982468-4584ff11f88a?ixlib=rb-4.0.3&q=85&fm=jpg&crop=entropy&cs=srgb&dl=neom-xDQKvPjxtxo-unsplash.jpg" 
     download="demo">下载图片</a>
function downLoadFile(res){
    const ele = document.createElement('a');
          ele.setAttribute('href',res.url); //设置下载文件的url地址
          ele.setAttribute('download' , 'download');//用于设置下载文件的文件名
          ele.click();
  
    link.addEventListener('click', (event) => {
      event.preventDefault();
      const downloadTimer = setTimeout(() => {
        alert('下载超时,请重试!');
      }, 5000); 

      const errorListener = () => {
        clearTimeout(downloadTimer);
        alert('下载失败!');
        link.removeEventListener('error', errorListener);
      };

      link.addEventListener('error', errorListener);
  });
}

window.onload = function(){
    $.ajax({
        url:"api/file/download",
        type:"get",
        dataType:'JSON'
    }).then(function(res){
        if(res.bizNO > 0 ){
            downLoadFile(res);
        }else{
            alert(res.bizMsg);
        }
   }).always(function(){
        alert("连接异常");
    })
}

扩展说明

关于优先级

Causes the browser to treat the linked URL as a download. Can be used with or without a filename value:

Without a value, the browser will suggest a filename/extension, generated from various sources:

The [Content-Disposition](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition) HTTP header → 上面的demo示例中,即使设置了dowmload属性,由于响应头中包含 Content-Disposition:attachment;filename="neom-xDQKvPjxtxo-unsplash.jpg",所以下载图片名称以响应头为准

filename: defining a value suggests it as the filename. / and \ characters are converted to underscores (_). Filesystems may forbid other characters in filenames, so browsers will adjust the suggested name if necessary.

关于响应头Content-Disposition

Content-Disposition 是一个 HTTP 响应头,它指定了如何显示响应的内容,特别是对于以附件形式下载的文件。这个头部可以包含一个内联展示(inline)的选项,也可以包含一个附件(attachment)的选项,以及可选的文件名参数。

主要作用如下:

1.内联展示(inline)

  • 如果Content-Disposition头部的值设置为inline,浏览器通常会尝试在浏览器窗口内显示内容,例如在浏览器中直接打开 PDF 文件或图像。
  • 这对于一些直接浏览的文件类型是合适的。

2.附件下载(attachment)

  • 如果Content-Disposition头部的值设置为attachment,浏览器通常会提示用户下载文件,而不是直接在浏览器中显示。
  • 这对于需要用户保存到本地的文件,如文档、图像、音频和视频等,是常见的设置。

3.指定文件名

通过filename参数,可以指定下载文件的文件名。这对于确保用户下载的文件有一个明确的名称非常有用,而不是使用服务器上的默认文件名。

例如,Content-Disposition: attachment; filename="example.txt"

方案2: Blob 下载

基础概念

什么是blob

blob是File类的超类,表示 二进制大对象,是JS对不可修改二进制数据的封装类型

blob相关知识点

developer.mozilla.org/zh-CN/docs/Web/API/Blob

适合场景

  • 接口返回的格式为文件流格式
  • 下载需要计算、权限验证、携带Cookie
  • 需要动态生成文件内容,即需要Post传参

代码实现

function fileDownLoad(data){
    // 1. 创建点击下载的元素   
    var linkElement = document.createElement('a');
  
    // 2. 判断浏览器是否支持blob对象
    try{
        //该实例化的方式第一个参数必须是数组的格式
        var blob = new Blob([data],{
          type: "application/pdf"
        });
    }catch(e){
        //旧版本浏览器下的blob创建对象
        window.BlobBuilder = window.BlobBuilder ||
                             window.WebKitBlobBuilder ||
                             window.MozBlobBuilder ||
                             window.MSBlobBuilder;
        if(e.name == 'TypeError' && window.BlobBuilder){
            var blobbuilder = new BlobBuilder();
            BlobBuilder.append(data);
            var blob = blobbuilder.getBlob("application/pdf");
        }else{
            alert("浏览器版本较低,暂不支持该文件类型下载");
        }
    }
  
    // 提取blob文件中的url信息,使二进制文件在不读取到js中时直接下载
    let url = window.URL.createObjectURL(blob);
    linkElement.setAttribute('href',url);
    linkElement.setAttribute('downLoad','download');
    linkElement.click();
    
    // 释放URL内存
    window.URL.revokeObjectURL(url);
}

document.querySelector('#fileInput').addEventListener('change', (event)=>{
  fileDownLoad(event.target.files[0])
})

下载接口需要携带Cookie信息

function downloadFileWithToken(url, token) {
    let xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.setRequestHeader("Authorization", token);
    xhr.responseType = 'blob';
    xhr.onload = function (e) {
        if (this.status === 200) {
            let blob = this.response;
            let fileName = '下载的文件名称';
            // 针对IE浏览器          
            if (window.navigator.msSaveBlob) {
                try {
                    window.navigator.msSaveBlob(blob, fileName);
                } catch (e) {
                    console.log(e);
                }
            } else {
                // 通用浏览器   
                const url = window.URL.createObjectURL(blob);
                a.href = url;
                a.download = fileName;
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                window.URL.revokeObjectURL(url);
            }
        } else {
            alert('下载文件失败');
        }
    }
    xhr.send();
}

方案3:FileSaver实现

基础介绍

基础使用

import FileSaver from 'file-saver'

let blob = new Blob(["Hello, FileSaver! Blob 下载"], {type: "text/plain;charset=utf-8"});
window.saveAs(blob, "hello FileSaver.txt");
import FileSaver from 'file-saver'

let blob = new Blob(["Hello, FileSaver! URL 下载"], {type: "text/plain;charset=utf-8"});
const url = window.URL.createObjectURL(blob)
window.saveAs(url, "hello FileSaver.txt");

原理介绍

以上就是JavaScript不同场景下的文件下载方案详解的详细内容,更多关于JavaScript文件下载的资料请关注脚本之家其它相关文章!

相关文章

  • JavaScript错误处理超完整实用指南

    JavaScript错误处理超完整实用指南

    在JavaScript中进行错误处理,最常见的方式就是使用try catch语句,下面这篇文章主要给大家介绍了关于JavaScript错误处理的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • Javascript 网页水印(非图片水印)实现代码

    Javascript 网页水印(非图片水印)实现代码

    在一些B/S结构的应用系统中,有很多页面是需要有水印的。常见的就是公文系统、合同系统等。
    2010-03-03
  • 深入浅析JS中的严格模式

    深入浅析JS中的严格模式

    严格模式就是使JS编码更加规范化的模式,消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为。下面通过代码相结合的形式给大家介绍js中的严格模式,感兴趣的朋友一起看看吧
    2018-06-06
  • js 事件的传播机制(实例讲解)

    js 事件的传播机制(实例讲解)

    下面小编就为大家带来一篇js 事件的传播机制(实例讲解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • D3.js实现绘制柱状图的教程详解

    D3.js实现绘制柱状图的教程详解

    这篇文章主要为大家详细介绍了如何通过D3.js实现绘制柱状图,文中的示例代码讲解详细,对我们学习D3.js有一定的帮助,需要的可以参考一下
    2022-11-11
  • JavaScript实现事件的中断传播和行为阻止方法示例

    JavaScript实现事件的中断传播和行为阻止方法示例

    这篇文章主要给大家介绍了利用JavaScript实现事件的中断传播和行为阻止的方法示例,文中给出了详细的介绍和示例代码,相信对大家的理解和学习具有一定的参考借鉴价值,需要的朋友们下面来一起看看吧。
    2017-01-01
  • 深入了解JavaScript阻塞渲染

    深入了解JavaScript阻塞渲染

    阻塞渲染就是在页⾯中我们通常会引⽤外部⽂件,⽽浏览器在解析HTML页⾯是从上到下依次解析、渲染,如果<head>中引⽤了⼀个a.js⽂件,⽽这个⽂件很⼤或者有问题,需要2秒加载,那么浏览器会停⽌渲染页⾯,2秒后加载完成才会继续渲染,这个就是阻塞
    2022-06-06
  • JS打开层/关闭层/移动层动画效果的实例代码

    JS打开层/关闭层/移动层动画效果的实例代码

    JS打开层/关闭层/移动层动画效果的实例代码,需要的朋友可以参考一下
    2013-05-05
  • 解析JavaScript中的不可见数据类型

    解析JavaScript中的不可见数据类型

    这篇文章主要是对JavaScript中的不可见数据类型进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-12-12
  • 基于JavaScript实现粒子流动效果

    基于JavaScript实现粒子流动效果

    这篇文章主要为大家详细介绍了如何通过JavaScript实现粒子流动效果,文中的示例代码讲解详细,具有一定的参考价值,感兴趣的小伙伴可以参考一下
    2023-09-09

最新评论