FileSaver.js源码学习,纯前端实现文件下载

简介: FileSaver.js源码学习,纯前端实现文件下载

背景


毕设项目的开发中,有文件下载的场景

其中文件直接从OSS(对象存储服务)上下载文件,使用a标签直接指向下载资源的方案存在一些小问题


如果文件类型是浏览器支持的类型的话,将会直接打开预览,不会调用下载

如在下载图片PDF等文件的时候如果直接打开预览,对用户来说非常不友好,体验较差

问题方案代码


function download(url){
  const a = document.createElement('a')
  a.target = '_blank'
  a.href = url
  document.body.append(a)
  a.click()
  a.remove()
}


首先想到的就是谷歌,然后就找到了这篇文章的主角FileSaver.js


FileSaver.js简介


机翻


FileSaver.js 是在客户端保存文件的解决方案,非常适合在客户端生成文件的 Web 应用程序,但是如果文件来自服务器,我们建议您首先尝试使用 Content-Disposition 附件响应 标题,因为它具有更多的跨浏览器兼容性。


简述


纯前端下载文件的解决方案


使用


import { saveAs } from 'file-saver';
saveAs('sourceUrl')
// or
saveAs('sourceUrl','filename')


API非常简洁(吃鲸.jpg),非常好用

抱着敬畏与学习的态度,戳开了仓库的源码,好家伙只有100多行代码,这不得好好学习一番...


核心的下载方法


扫两遍源码,很快总结出了最小的,可运行代码

补齐了一些注释后如下


function download(url, name) {
  var xhr = new XMLHttpRequest()
  xhr.open('GET', url)
  // 设置返回数据的类型为blob
  xhr.responseType = 'blob'
  // 资源完成下载
  xhr.onload = function () {
    // 获取响应的blob对象
    const blob = xhr.response
    const a = document.createElement('a')
    // 设置下载的文件名字
    name = name || blob.name || 'download'
    a.download = name
    // 解决安全问题,新页面的window.opener 指向前一个页面的window对象
    // 使用noopener使 window.opener 获取的值为null
    a.rel = 'noopener'
    // 创建一个DOMString指向这个blob
    // 简单理解就是为这个blob对象生成一个可访问的链接
    a.href = URL.createObjectURL(blob)
    // 40s后移除这个临时链接
    setTimeout(function () { URL.revokeObjectURL(a.href) }, 4E4) // 40s
    // 触发a标签,执行下载
    setTimeout(function () {
      a.dispatchEvent(new MouseEvent('click'))
    }, 0)
  }
  // 发送请求
  xhr.send()
}


使用示例


<body>
    <button id="btn">下载</button>
    <script src="./index.js"></script>
</body>


document.getElementById('btn').addEventListener('click', function () {
  const url = 'https://img.cdn.sugarat.top/mdImg/MTU3OTM2ODc3OTM4Nw==579368779387'
  download(url)
})


总结一下就是使用URL.createObjectURL(blob)为资源的创建一个临时的链接进行下载


浏览器会直接将这资源下载到本地,不会进行预览


发现的缺陷


大文件需要等待长时间


由于使用了xhr实现,在xhr.onload是在资源完全响应后才会触发

这就存在一个问题,如果文件非常大,那么需要等待很久,才会执行下载(直接完成)

用户无法感知到这个下载过程,会以为下载没生效(传统的下载会由浏览器接管,所以用户能看到进度),疯狂的连续多次的点击


我们需要监听下载的进度,用于提醒用户,下面拓展一下上面的download方法:


  • 监听onprogress方法
  • 获取totalloaded这两个属性
  • 相除得到下载进度


function download(url, name) {
  var xhr = new XMLHttpRequest()
  xhr.open('GET', url)
  xhr.responseType = 'blob'
  // 增加的代码
  xhr.onprogress = function (e) {
    const { total,loaded } = e
    const percentage = (loaded/total).toFixed(2)
    console.log('progress:', percentage);
  }
  xhr.onload = function () {
    // 省略...跟前面的代码一致
  }
  xhr.send()
}


示例


找了一个稍微大一点的图片进行测试,可以发现在网速慢的时候还是需要一定的时间才能完成下载


download('https://img.cdn.sugarat.top/mdImg/MTYyMzA3NjA4NDQ4NA==desktop.jpg')


总结


  • 适合解决下载图片,PDF等文件被浏览器直接打开的情况
  • 针对比较大的资源,可以改造一下,反馈下载进度,提升用户体验


偶尔遇到一些工具库,源代码不多的话,可以花些时间看看,精炼精炼,然后变成自己的东西


相关文章
|
29天前
|
JavaScript 前端开发 程序员
前端原生Js批量修改页面元素属性的2个方法
原生 Js 的 getElementsByClassName 和 querySelectorAll 都能获取批量的页面元素,但是它们之间有些细微的差别,稍不注意,就很容易弄错!
|
3天前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
22 3
|
26天前
|
JavaScript 前端开发 Java
springboot解决js前端跨域问题,javascript跨域问题解决
本文介绍了如何在Spring Boot项目中编写Filter过滤器以处理跨域问题,并通过一个示例展示了使用JavaScript进行跨域请求的方法。首先,在Spring Boot应用中添加一个实现了`Filter`接口的类,设置响应头允许所有来源的跨域请求。接着,通过一个简单的HTML页面和jQuery发送AJAX请求到指定URL,验证跨域请求是否成功。文中还提供了请求成功的响应数据样例及请求效果截图。
springboot解决js前端跨域问题,javascript跨域问题解决
|
28天前
|
缓存 JavaScript 前端开发
JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用
本文深入讲解了 JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用。
41 5
|
26天前
|
缓存 前端开发 JavaScript
JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式
本文深入解析了JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式(Hash路由和History路由)、优点及挑战,并通过实际案例分析,帮助开发者更好地理解和应用这一关键技术,提升用户体验。
65 1
|
1月前
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
35 4
|
1月前
|
前端开发 开发者 C++
独家揭秘:前端大牛们如何高效学习新技术,保持竞争力!
【10月更文挑战第31天】前端技术飞速发展,如何高效学习新技术成为关键。本文通过对比普通开发者与大牛们的策略,揭示了高效学习的秘诀:明确目标、主动探索、系统资源、实践应用和持续学习。通过这些方法,大牛们能更好地掌握新技术,保持竞争力。示例代码展示了如何通过实践加深理解。
44 4
|
1月前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
113 1
|
1月前
|
移动开发 前端开发 JavaScript
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
于辰在大学期间带领团队参考网易游戏官网的部分游戏页面,开发了一系列前端实训作品。项目包括首页、2021校园招聘页面和明日之后游戏页面,涉及多种特效实现,如动态图片切换和人物聚合效果。作品源码已上传至CSDN,视频效果可在CSDN预览。
41 0
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
|
1月前
|
JavaScript 前端开发 开发者
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第27天】在前端开发领域,Vue.js和Angular是两个备受瞩目的框架。本文对比了两者的优劣,Vue.js以轻量级和易上手著称,适合快速开发小型到中型项目;Angular则由Google支持,功能全面,适合大型企业级应用。选择时需考虑项目需求、团队熟悉度和长期维护等因素。
47 1
下一篇
DataWorks