通过JavaScript下载文件到本地(单个文件)
目前正在做一个文件下载功能,在此简单总结一下过程中使用的技巧和陷阱。1.单文件下载(a标签)同源单个文件在单个文件的情况下,可以通过标签的download属性下载同源文件constelt=document.createElement('A');埃尔特。setAttribute('href',网址);elt.setAttribute('下载','file.png');elt.style.display='无';文档.body.appendChild(elt);elt.click();文件.body.removeChild(elt);但是这种方案不适用于非同源资源。这时候就相当于一个普通的超链接。点击它会跳转到资源页面而不是下载。如果异源图片没有CORS问题,可以使用Blob下载(构造xhr请求文件地址,接收Blob形式的Response):functiondownloadWithBlob(url){fetch(url).then(res=>res.blob().then(blob=>{vara=document.createElement('a');varurl=window.URL.createObjectURL(blob);varfilename='file.png';a.href=url;a.download=filename;a.click();window.URL.revokeObjectURL(url);}));}如果有CORS问题,可以考虑使用canvas将图片转成base64编码然后通过tagfunctiondownloadPic(url){constimg=newImage;的download属性进行下载constcanvas=document.createElement('canvas');constctx=canvas.getContext('2d');img.onload=function(){canvas.width=this.width;帆布。height=this.height;ctx.drawImage(this,0,0);constelt=document.createElement('a');elt.setAttribute('href',canvas.toDataURL('image/png'));elt.setAttribute('下载','file.png');elt.style.display='无';文档.body.appendChild(elt);elt.click();文档.body.removeChild(elt);};img.crossOrigin='匿名';img.src=url;}2.单文件下载(iframe)iframe方法是将iframe隐藏在页面中,然后将下载地址加载到iframe中,从而触发浏览器的下载行为constiframe=document。createElement('iframe');iframe.src=url;iframe.style.display='无';document.body.appendChild(iframe);但是这里发现连同域的图片都无法下载完成,这是为什么呢?这里提一个上面链接下载没有提到的问题:whatkindoflinkcantriggerthebrowsertodownload:url如何触发浏览器自动下载?一个url能否触发浏览器自动下载主要看请求响应头response头是否满足一般取决于两个消息头Content-Disposition和Content-Type:响应头指定Content-Disposition为附件,意思是让浏览器将消息体作为附件下载并保存到本地(一般也会指定filename,下载的文件名默认为filename)。Content-Type在响应头中指定为application/octet-stream(无类型)或application/zip(用于zip包)等(其中application/octet-stream表示http响应是二进制流(未指定明确类型),用于未知应用程序文件。浏览器一般不会自动执行或请求执行,浏览器会把文件当做HTTP头Content-Disposition值设置为attachment来对待这样的文件)只要url满足上面的触发要求,就可以在下载iframe的形式3.代理服务处理下载如果后端也能控制,或者后端能配合,可以写一个代理服务,去后端请求文件数据,然后设置相应的响应头,然后请求代理服务在前端下载。前端(假设代理服务接口为http://exampale.com/download):constdownloadUrl='http://exampale.com/download?url='+encodeURIComponent(url)+'&name=xxx';constelt=document.createElement('a');elt.setAttribute('href',downloadUrl);elt.setAttribute('下载','file.png');...后端consturl=decodeURIComponent(req.query.url);http.get(url,(response)=>{res.setHeader('Content-disposition','attachment;filename='+req.query.name);res.setHeader('Content-type','application/octet-stream');response.pipe(res);});单个文件的处理先写到这里,下一部分再写多个文件的下载。