前端 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文件下载的资料请关注毛票票其它相关文章!