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等文件被浏览器直接打开的情况
  • 针对比较大的资源,可以改造一下,反馈下载进度,提升用户体验


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


相关文章
|
8月前
|
前端开发 JavaScript 算法
【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
transition过渡属性 早期在Web中要实现动画效果,都是依赖于JavaScript或Flash来完成。 但在CSS3中新增加了一个新的模块transition,它可以通过一些简单的CSS事件来触发元素的外观变化, 让效果显得更加细腻。简单点说,就是通过鼠标经过、获得焦点,被点击或对元素任何改变中触发, 并平滑地以动画效果改变CSS的属性值。 在CSS中创建简单的过渡效果可以从以下几个步骤来实现: 在默认样式中声明元素的初始状态样式; 声明过渡元素最终状态样式,比如悬浮状态; 在默认样式中通过添加
398 1
|
8月前
|
前端开发 JavaScript 算法
【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
transform变形 css3在原来的基础上新增了变形和动画相关属性,通过这些属性可以实现以前需要大段JavaScript才能实现的 功能。 CSS3的变形功能可以对HTML组件执行位移、旋转、缩放、倾斜4种几何变换,这样的变换可以控制HTML组件 呈现出丰富的外观。 借助于位移、旋转、缩放、倾斜这4种几何变换,CSS3提供了transition动画。 transition动画比较简单,只要指定HTML组件的哪些CSS属性需要使用动画效果来执行变化,并指定动画时间,就可保证动画播放。 比transitio
393 1
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
1201 1
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
723 70
|
JavaScript 前端开发 API
|
存储 前端开发 JavaScript
|
前端开发 JavaScript 数据可视化
58K star!这个让网页动起来的JS库,前端工程师直呼真香!
Anime.js 是一款轻量级但功能强大的JavaScript动画引擎,它能够以最简单的方式为网页元素添加令人惊艳的动效。这个项目在GitHub上已经获得58,000+星标,被广泛应用于电商页面、数据可视化、游戏开发等场景。
592 8
|
JavaScript 前端开发 容器
|
JavaScript 前端开发
|
存储 JavaScript 前端开发

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    1169
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    513
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    398
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    393
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    508
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    680
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    1207
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    272
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    1003
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    470