前端 javascript 实现文件下载的示例
在html5中,a标签新增了download属性,包含该属性的链接被点击时,浏览器会以下载文件方式下载href属性上的链接。示例:
下载
1.前端js下载实现与示例
通过javascript动态创建一个包含download属性的a元素,再触发点击事件,即可实现前端下载。
代码示例:
functiondownload(href,title){ consta=document.createElement('a'); a.setAttribute('href',href); a.setAttribute('download',title); a.click(); }
说明:
- href属性设置要下载的文件地址。这个地址支持多种方式的格式,因此可以实现丰富的下载方法。
- download属性设置了下载文件的名称。但href属性为普通链接并且跨域时,该属性值设置多数情况下会被浏览器忽略。
1.1普通连接下载示例
//下载图片 download('https://lzw.me/images/gravatar.gif','lzwme-gravatar'); //下载一个连接 download('https://lzw.me','lzwme-index.html');
1.2href为dataURIs示例
dataURI是前缀为data:scheme的URL,允许内容创建者在文档中嵌入小文件。数据URI由四个部分组成:前缀(数据:),指示数据类型的MIME类型,如果非文本则为可选的base64令牌,数据本身:
data:[][;base64],
链接的href属性为dataURIs时,也可以实现文件内容的下载。示例:
download('data:,Hello%2C%20World!','data-uris.txt'); download('data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D','data-uris.txt');
1.3canvas下载示例
对于canvas可以通过toDataURL方法取得dataURIs格式的内容。
1.4二进制内容下载
URL.createObjectURL方法会根据传入的参数创建一个指向该参数对象的URL。新的对象URL指向执行的File对象或者是Blob对象。
URL.createObjectURL的参数是File对象或者Blob对象,File对象也就是通过input[type=file]选择的文件,Blob对象是二进制数据。
将URL.createObjectURL返回值设为href属性的值,即可实现二进制内容下载。示例:
constcontent='Welcometolzw.me!'; constblob=newBlob([content]); consthref=URL.createObjectURL(blob); download(href,'download-text.txt'); URL.revokeObjectURL(href);
1.5前端下载方法示例
综合上述讨论,这里给出一个前端实现下载的saveAs方法的TypeScript示例:
/** *通过创建adom对象方式实现前端文件下载 *@paramhref要下载的内容链接。当定义了toBlob时,可以为纯文本或二进制数据(取决于toBlob格式 *@paramfileName下载后的文件名称 *@paramtoBlob如设置该参数,则通过blob方式将href转换为要保存的文件内容,该参数将入参为newBlob([href],toBlob)的第二个参数 *@example *```js *saveAs('abc','abc.txt',{}); *saveAs('data:,Hello%2C%20World!','hello.txt'); *saveAs('https://lzw.me/images/avatar/lzwme-80x80.png','lzwme-logo.png'); *``` */ exportfunctionsaveAs(href:string|Blob,fileName?:string,toBlob?:PlainObject){ constisBlob=hrefinstanceofBlob||toBlob; if(!fileName&&typeofhref==='string'&&href.startsWith('http')){ fileName=href.slice(href.lastIndexOf('/')+1); } fileName=decodeURIComponent(fileName||'download'); if(typeofhref==='string'&&toBlob)href=newBlob([href],toBlob); if(hrefinstanceofBlob)href=URL.createObjectURL(href); constaLink=document.createElement('a'); aLink.setAttribute('href',href); aLink.setAttribute('download',fileName); aLink.click(); //constevt=document.createEvent("HTMLEvents"); //evt.initEvent("click",false,false); //aLink.dispatchEvent(evt); if(isBlob)setTimeout(()=>URL.revokeObjectURL(aLink.href),100); returnaLink; }
2.检测浏览器是否支持download属性
download属性为html5新增内容,浏览器支持情况可参考:http://caniuse.com/#feat=download
判断浏览器是否支持该属性,只需要检测a标签是否存在download属性。示例:
constdownloadAble='download'indocument.createElement('a');
对于不支持的浏览器,只能另想他法或者予以降级处理了。
3.使用serviceWorker和fetchAPI代理实现
前端下载更多的需求是因为内容产生于前端。那么可以在后端实现一个这样的API,它在接收到前端发出的内容后返回下载格式的数据。这种实现就不存在浏览器兼容问题。
利用serviceWorker和fetchAPI截拦浏览器请求,只需实现好约定逻辑,也可实现这种功能需求。示例:
在页面中,通过fetchAPI构造请求:
fetch('lzwme.txt',{ isDownload:true, body:{ data:newBlob('hi!') } })
在serviceWorker中,截拦附带isDownload头信息的请求,构造下载回应:
self.addEventListener('fetch',function(event){ constreq=event.request; if(!req.headers.get('isDownload')){ retrunfetch(req); } constfilename=encodeURIComponent(req.url); constcontentType=req.headers.get('Content-Type')||'application/force-download'; constdisposition="inline;filename="+filename+";filename*=utf-8''"+filename constmyBody=req.headers.get(body).data; event.respondWith( newResponse(myBody,{ headers:{ 'Content-Type':contentType, 'Content-Disposition':disposition } }) ); });
4使用ajax(xhr与fetchAPI)方式下载服务器文件
以上主要讨论的是纯前端实现下载保存文件的方法。对于下载服务器文件,最简的方式就是window.open(url)和location.href=url了,但是其的弊端也很明显,当出错时整个页面都会挂掉,而且也无法获得下载状态与进度,下载时间稍长时体验相当不好。
下面介绍一下使用xhr和fetchAPI实现文件下载的方法。其主要思路为:将请求结果设为Blob类型,然后采用前端下载保存Blob类型数据的方式实现下载。
4.1使用xhr下载远程服务器文件
代码示例:
/**前端下载/保存文件*/ functionsaveAs(href,fileName){ constisBlob=hrefinstanceofBlob; constaLink=document.createElement('a'); aLink.href=isBlob?window.URL.createObjectURL(href):href; aLink.download=fileName; aLink.click(); if(isBlob)setTimeout(()=>URL.revokeObjectURL(aLink.href),100); } functionxhrDownload(url,options={}){ options=Object.assign({method:'get',headers:{}},options); returnnewPromise((reslove,reject)=>{ constxhr=newXMLHttpRequest(); xhr.responseType='blob';//options.responseType; if(options.headers){ for(constkeyinoptions.headers)xhr.setRequestHeader(key,options.headers[key]); } xhr.onload=()=>{ //从Content-Disposition中获取文件名示例 constcd=xhr.getResponseHeader('Content-Disposition'); if(cd&&cd.includes('fileName')&&!options.fileName)options.fileName=cd.split('fileName=')[1]; options.fileName=decodeURIComponent(options.fileName||'download-file'); if(+xhr.status==200){ saveAs(xhr.response,options.fileName); reslove(options.fileName);
使用fecthAPI下载远程服务器文件
functionfetchDownload(url,options={}){ options=Object.assign({credentials:'include',method:'get',headers:{}},options); returnfetch(url,options).then(response=>{ returnresponse.blob().then(blob=>{ if(!blob||!blob.size)returnPromise.reject('empty'); //从Content-Disposition中获取文件名示例 constcd=response.headers.get('Content-Disposition'); if(cd&&cd.includes('fileName')&&!options.fileName)options.fileName=cd.split('fileName=')[1]; options.fileName=decodeURIComponent(options.fileName||'download-file'); saveAs(blob,options.fileName); returnoptions.fileName; }); }); } //测试 fetchDownload('https://lzw.me/images/avatar/lzwme-80x80.png',{ //method:'post', //headers:{ // 'Content-Type':'application/json' //}, //body:JSON.stringify({ // pageSize:100000, // startPage:0 //}) })
以上就是前端javascript实现文件下载的示例的详细内容,更多关于JavaScript文件下载的资料请关注毛票票其它相关文章!