前端培训-初级阶段-场景实战(2019-06-06)-下载文件&下载速度

简介: 前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS),本着提升技术水平,打牢基础知识的中心思想,我们开课啦(每周四)。

这两天,碰到了不止一次前端下载的的问题。其实之前我写过一篇文章 download使用浅析,主要依靠 download 属性来实现浏览器端下载,因为是走浏览器的下载,所以没有进度条。今天我们就来说说我的解决方案。


1. sf 的一个问题,需要显示进度条。答案地址,问题地址


2. 一个朋友的问题,下载的文件需要 headers 验证,无奈只能 ajax 拿数据。


  1. 一个朋友的问题,监测下载进度。


今天我们要讲什么?


  1. 如何使用 download 属性,下载文件。
    这节主要是讲如何使用,以及前端下载的核心操作。


  1. 下载文件,并显示进度条。
    这节是正常操作,如果你只为了解原理,看到这里就够了


  1. 其他数据类型如何互相转换
    这节就不一样了。因为之前的 api 是使用 blob 实现,但是 ajax 传回来的数据有好多种类型,我们如何将他们相互转换?


如何使用 download 属性,下载文件。


download使用浅析 这一文中已经介绍了,可以去看看。我这里简单说一下。标签如果设置了 download 属性,他就会去下载这个地址。测试地址-原生 download 属性测试


下载文件,并显示进度条


下载文件上面已经实现了,那我们先说说如何显示进度条。


显示进度条


其实浏览器也是有进度条的,但是咱们拿不到。那我们就来模拟一下载,然后显示进度条。


  1. ajax 实现下载进度条,测试地址-显示进度条
xhr = new XMLHttpRequest();
xhr.open('get', file1.url);
xhr.onprogress = (e)=>console.log(e)//e 就是一个 ProgressEvent 对象,其中 loaded 是已下载的, total 是总大小。
xhr.send()


2.fetch 实现下载进度条,测试地址-fetch显示进度条并下载


fetch 的实现上来说有一些功能是没有的,比如 abort、进度等。那我们就需要去通过一些别的手段来模拟实现。


实现代码如下,我们操作成读流,然后统计长度。


bVbtb2M.webp.jpg


下载文件


进度条已经显示好了,那我们可以下载文件了。首先我们要分几种情况

  1. 缓存下载(一个资源如果已经下载完了,再次去访问)


4110456011-5cec8a644e222_fix732.png


  1. 本地下载(资源已经在浏览器中)


  1. blob url 下载 如这种地址 blob:https://www.lilnong.top/deb4c297-821c-4545-9b23-0fbdd76890c7

971268328-5cec8ac85d8ad.png


   b.base64 url 下载 如这种地址 data:application/octet-stream;base64,aGVsbG8gbGlub25n


blob = new Blob(['hello linong'])
  freader = new FileReader()
  freader.readAsDataURL(blob)//将 blob 读成 dataurl
  freader.onload=e=>console.log(freader.result)// 异步的,所以需要回调里面拿


 bVbtb5k.webp.jpg


3.无缓存下载(资源没在本地,也没有缓存)


情况就是上面几种,那我们要做的其实就是统一一下流程


  1. ajax 拉取数据(显示进度条)


  1. 缓存了数据,然后下载缓存(因为是缓存,所以秒下)


  1. 浏览器缓存
    我比较推荐用这个,因为其他的方案都有大小或者兼容上的问题。但是这个缓存需要服务器设置需要走缓存。
  2. bloburl 本地缓存下载
    这个方案在移动端异常,pc端正常,感兴趣的小伙伴可以自己实现一下,毕竟学了这么多,得用起来才能变成自己的
  3. dataurl 本地缓存下载
    这个方案的支持会比 bloburl 好一点,但是只适用于小文件。


实现前端下载文件并显示进度条


我们让 ajax 直接返回 blob。然后构建 bloburl 用于下载。


downloadFile2 = (url)=>{
    var xhr = new XMLHttpRequest();
    xhr.open('get', url);
    xhr.responseType='blob';//这是精髓
    xhr.onprogress = onprogress2;//下载进度
    // .upload.onprogress 这个是上传的时候的进度
    xhr.onreadystatechange = ()=>{
        if(xhr.readyState == 4 && xhr.status == 200){
            nativeDownload(URL.createObjectURL(xhr.response))
        }
    }
    xhr.send()
}


其他类型转换为 blob


如果是一些封装过的 ajax,没办法使用 xhr.responseType='blob' 之类的,返回回来是字符串。那我们需要怎么出转换呢?


blob to *


blob 需要配合 FileReader 来读取


  1. blob to arrayBufferreadAsArrayBuffer
    通用的、固定长度的原始二进制数据缓冲区


var fileReader = new FileReader();
fileReader.readAsArrayBuffer(xhr.response);//xhr.reponse 是 blob 类型
fileReader.onload = e=>console.log(fileReader.result);

bVbtcnI.webp.jpg


2.blob to DataURLreadAsDataURL


Base64 是一组相似的二进制到文本(binary-to-text)的编码规则,使得二进制数据在解释成 radix-64 的表现形式后能够用 ASCII 字符串的格式表示出来。Base64 这个词出自一种 MIME 数据传输编码。 --MDN

bVbtcn5.webp.jpg

3.blob to TextreadAsText


以字符串表示所读取的文件内容


bVbtcox.webp.jpg


4.blob to BinaryStringreadAsBinaryString
文件的原始二进制数据


bVbtcoE.webp.jpg


* to blob


  1. arrayBuffer to blob
    new Blob([arrayBuffer], {type: 'image/jpeg'})


  1. base64 to blob


(new Uint8Array(Array.from(atob(base64url.split(',')[1])).map(v=>v.charCodeAt()))).buffer
//base64url.split(',')[1] //截取不要 data:images/jpeg;base64, 这串
//atob //转换成 BinaryString
//Array.from //转换成数组
//map(v=>v.charCodeAt()) //转换成对应的 ascii 码
//Uint8Array 转换成 Uint8Array 然后输出 buffer


1305284727-5cecc605eb7aa_fix732.png


3.BinaryString to blob


方案同上,因为上面的也是转换成了BinaryString


4.Text to blob


ajax 默认就是 Text 类型的返回值。这个我觉得是编码类型的转换,比如 utf-8 to ascii,目前我还没找到好的实现方法。


view.webp (7).jpg

总结


之前就写过一篇AJAX 的进阶使用(Blob、ArrayBuffer、FormData、Document、JSON、Text),里面讲了这些支持的类型。


base64转换上传,也写过这样的。


前端目前需要操作的东西越来越多了。


在最上面那个问答里,有个库去实现 download 操作。实现原理可以自己去看看。


后记


参考资料


  1. Data URLs --MDN
  2. StringView
  3. 字符编码中ASCII、Unicode和UTF-8的区别
  4. String.prototype.charCodeAt()
  5. DOMString
  6. rfc2397
相关文章
|
1天前
|
JSON JavaScript 前端开发
vue的 blob文件下载文件时,后端自定义异常,并返回json错误提示信息,前端捕获信息并展示给用户
vue的 blob文件下载文件时,后端自定义异常,并返回json错误提示信息,前端捕获信息并展示给用户
|
1天前
|
缓存 前端开发 UED
实战指南:如何优化前端性能提升用户体验
本文探讨了在当今互联网时代,前端性能优化对于提升用户体验的重要性,以及如何利用各种技术手段实现前端性能的优化。通过介绍前端性能优化的原则、常见的性能优化技巧和工具,以及实际案例分析,帮助开发者深入了解并掌握提升前端性能的方法,从而提升网站的加载速度、响应速度,提高用户的满意度和留存率。
|
10天前
|
前端开发 JavaScript
【Web 前端】什么是扩展运算符,用于什么场景?
【5月更文挑战第1天】【Web 前端】什么是扩展运算符,用于什么场景?
【Web 前端】什么是扩展运算符,用于什么场景?
|
12天前
|
JSON JavaScript 前端开发
前端框架vue的样式操作,以及vue提供的属性功能应用实战
前端框架vue的样式操作,以及vue提供的属性功能应用实战
|
12天前
|
JavaScript 前端开发 数据安全/隐私保护
优秀的前端框架vue,原理剖析与实战技巧总结【干货满满】(二)
优秀的前端框架vue,原理剖析与实战技巧总结【干货满满】(二)
|
12天前
|
JavaScript 前端开发 Python
优秀的前端框架vue,原理剖析与实战技巧总结【干货满满】(一)
优秀的前端框架vue,原理剖析与实战技巧总结【干货满满】(一)
|
12天前
|
前端开发 JavaScript 数据安全/隐私保护
前端javascript的DOM对象操作技巧,全场景解析(二)
前端javascript的DOM对象操作技巧,全场景解析(二)
|
9月前
|
Web App开发 前端开发 JavaScript
前端学习笔记202307学习笔记第五十七天-模拟面试笔记react-fiber解决了什么问题
前端学习笔记202307学习笔记第五十七天-模拟面试笔记react-fiber解决了什么问题
98 0
|
9月前
|
前端开发 定位技术
前端学习笔记202305学习笔记第二十三天-地图单线程配置
前端学习笔记202305学习笔记第二十三天-地图单线程配置
68 0
前端学习笔记202305学习笔记第二十三天-地图单线程配置
|
9月前
|
前端开发 API
前端学习笔记202307学习笔记第五十七天-模拟面试笔记react-react-redux的工作流程
前端学习笔记202307学习笔记第五十七天-模拟面试笔记react-react-redux的工作流程
55 0