前端最基础的就是HTML+CSS+Javascript。掌握这三项技术算是入门,但也只是入门而已。现在前端开发的定义远不止于此。前端小课堂(HTML/CSS/JS),本着提高技术水平,夯实基础知识的中心思想,开课(每周四)。这两天遇到的前端下载问题不止一个。其实之前写过一篇分析download使用的文章,主要是靠download属性实现浏览器端下载,因为是通过浏览器下载,所以没有进度条。今天我们就来说说我的解决方法。sf需要显示进度条的问题。回答地址,问题地址朋友的问题,下载的文件需要通过headers校验,但是我只能通过ajax获取数据,但是返回的字符串还是字符串,需要自己处理。朋友的问题,监控下载进度。我们今天要谈什么?如何使用download属性下载文件。本节主要讲一下如何使用,以及前端下载的核心操作。下载文件并显示进度条。本节为正常操作。如果只是想了解原理,看这里就够了。其他数据类型如何相互转换,本节有所不同。因为之前的api是使用blob实现的,但是ajax返回的数据类型很多,我们如何相互转换呢?如何使用download属性下载文件。关于下载的使用分析本文已经介绍过了,大家可以去看看。我在这里简单说一下。如果标签设置了download属性,它将下载这个URL。测试URL-本机下载属性测试。下载文件并显示进度条下载文件上面已经实现了,那我们先来说说如何显示进度条。显示进度条其实浏览器也是有进度条的,只是我们获取不到而已。那我们就模拟一次下载,然后显示进度条。Ajax实现下载进度条,测试地址-显示进度条xhr=newXMLHttpRequest();xhr.open('get',file1.url);xhr.onprogress=(e)=>console.log(e)//e是一个ProgressEvent对象,这里loaded是下载,total是总大小。xhr.send()fetch实现下载进度条,测试地址-fetch显示进度条和downloadsfetch的实现有一些功能是没有的,比如abort,progress等,那我们就需要借助一些其他的手段来模拟实现。实现代码如下,我们作为读流操作,然后统计长度。已经显示下载文件进度条,接下来我们就可以下载文件了。首先,我们需要在几种情况下对下载进行缓存(如果某个资源已经下载过,则再次访问)本地下载(该资源已经在浏览器中)bloburl下载比如这个地址blob:https://www.lilnong.top/deb4c297-821c-4545-9b23-0fbdd76890c7base64url??下载比如这个地址data:application/octet-stream;base64,aGVsbG8gbGlub25nblob=newBlob(['hellolinong'])freader=newFileReader()freader.readAsDataURL(blob)//将blob读入dataurlfreader.onload=e=>console.log(freader.result)//异步,所以需要在回调中下载无缓存(资源不在本地),并且没有缓存)。情况就是上面几种,那么我们要做的就是统一流程,ajax拉取数据(显示进度条),缓存数据,然后下载缓存(因为是缓存,所以会下载很快)。我推荐这个浏览器缓存,因为其他解决方案都存在大小或兼容性问题。但是这个缓存需要服务器设置,需要缓存。bloburl本地缓存下载解决方法在移动端异常,但PC端正常。有兴趣的朋友可以自己实现。毕竟学了这么多,还得拿来用,变成自己的dataurl。该方案对本地缓存下载的支持会比bloburl好一点,但仅限于小文件。实现前端下载文件和显示进度条,我们让ajax直接返回blob。然后构建bloburl以供下载。downloadFile2=(url)=>{varxhr=newXMLHttpRequest();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'之类的,返回的是字符串。那么我们需要如何转换呢?blobto*blob需要配合FileReader读取blobtoarrayBuffer(readAsArrayBuffer)一个通用的,固定长度的原始二进制数据缓冲区varfileReader=newFileReader();fileReader.readAsArrayBuffer(xhr.response);//xhr.响应是blob类型fileReader.onload=e=>console.log(fileReader.result);blobtoDataURL(readAsDataURL)Base64是一套类似二进制转文本的编码规则,使二进制数据解释为radix-64的表达形式,可以用ASCII字符串的格式来表达。术语Base64来自MIME数据传输编码。--MDNblobtoText(readAsText)将读取的文件内容表示为字符串blobtoBinaryString(readAsBinaryString)文件的原始二进制数据*toblobarrayBuffertoblobnewBlob([arrayBuffer],{type:'image/jpeg'})base64到blob(newUint8Array(Array.from(atob(base64url.split(',')[1])).map(v=>v.charCodeAt()))).buffer//base64url.split(',')[1]//不截取data:images/jpeg;base64,thisstring//atob//转换为BinaryString//Array.from//转换为数组//map(v=>v.charCodeAt())//转换成对应的ascii码//Uint8Array转换成Uint8Array然后输出bufferBinaryString到blob方案同上,因为上面也是转换成BinaryStringText到blobajax,也就是Text类型的返回值默认。我觉得这是编码类型的转换,比如utf-8到ascii,目前还没找到好的实现方式。在总结之前,我写了一篇AJAX的进阶使用(Blob、ArrayBuffer、FormData、Document、JSON、Text),里面讲了这几种支持的类型。base64转换上传,也写了这个。前端需要操作的东西越来越多。在置顶问答中,有一个库来实现下载操作。实现原理大家自己看吧。PostscriptReferenceDataURLs--MDNStringView字符编码中ASCII、Unicode和UTF-8的区别String.prototype.charCodeAt()DOMStringrfc2397
