要求说明:
后端接口返回包含URL的附件列表。 这些附件驻留在Alibaba云操作系统中。 第一期需求是实现点击下载列出的附件。 也就是说,每次只下载点击的附件(PDF |图像)。 使用一段时间后,在制定二期需求时,需要增加批量下载功能,并随附。 附言:文中写的都是纯前端实现,后端接口只需要返回路径。
单独下载图像:
如果直接使用标签,则可以通过在标签中指定download属性来避免单击同源链接并直接在浏览器中打开,但问题是如果不是同源链接则无法打开。 因此采用Canvas JS方式实现图片点击直接下载,这里有1、解决非同源、跨域问题2、Canvas图片下载限制问题。 同源问题得到很好的解决,一行代码即可:
image.set attribute (' cross origin ',' anonymous ' )。
为了解决Canvas图像的像素大小限制并将其转换为blod流数据,请在下面添加代码。
//*
* @param {Number} imgsrc图像路径
* @param {Number} name自定义图像名称
*直接在canvas下载由于图像的像素大小有限,因此转换为blod流下载
*/downloadiamge(imgsrc,name ) /下载图像地址和图像名称
解决let image=newImage ()//域间Canvas污染问题
image.set attribute (' cross origin ',' anonymous ' )。
let fun=this.dataURLtoBlob
image.nlad=function () {
创建let Canvas=document.createelement (' canvas ' ) canvas
canvas.width=image.width
canvas.height=image.height
let context=canvas.get context (' 2d ' ) )。
context.drawimage(image,0,0,image.width,image.height )//Canvas图
使用leturl=canvas.toDataURL ({ format : ' png ',multiplier: 4} ) todataurl )方法将图像转换为URL
从varblod=fun(URL ) varobjURL=URL.createobjectURL ) blob ) /转换为blod
生成leta=document.createelement('a ' )//a元素
letevent=newmouseevent('click ' )//创建单击事件
a.download=name || ''photo' //设置图像名称
a.href=objurl //将生成的URL设置为a.href属性
a .分布式事件(事件) /触发器a的单击事件
}
image.src=imgsrc '? 添加=' Math.random ()//随机数以解决无法跨域下载的问题
、/**
* @ param { string }数据URL图像地址
迁移到blod流*/dataurltoblob (数据URL )
let arr=dataurl.split (',')
letmime=arr[0].match(/: ).*? ); //[1]
letbstr=atob(ARR[1] ) ) ) ) ) ) ) ) )。
let n=bstr.length
letu8ARR=newuint8Array(n ) while(n-- ) {
u8ARR[n]=bstr.charcodeat(n ) )。
}返回新建blob ([ u8arr ],{type: mime} ) ) ) ) ) ) ) ) )。
}
在实现过程中,如果以这种方式指定image的src属性,则:
image.src=imgsrc
运行后,非同源图像直接打开的问题没有得到解决,因此在下载地址后添加了随机数
image.src=imgsrc '?=' Math.random () )。
批量下载:
这里使用的是JSZip (用于文件打包)和文件服务器。 因为要在Vue项目中使用,所以直接在项目中下载
npm install jszip
NPM安装文件-服务器
部署到要使用的文件:
导入js zip from ' js zip ';
导入文件服务器自' from ' file-saver ';
要下载主方法代码,请执行以下操作:
//批量下载
async down () {try{
let zip=newJSZip (; for(letI=0; i this.arr.length; I ) {
let lst=this.arr[i].split ('.';
let fileType=lst[lst.length - 1]; if (filetype.tolocaleuppercase (==' pdf ' ) )
aitthis.getfile(this.arr[I] ).then ) pdf={
zip.file(hellopdf.pdf )、pdf、{ binary: true} );
);
}else{
ait this.get base64 image (this.arr [ I ] ).then ) RES={
zip.file(helloimg'I'.'filetype,res,{ base64: true} );
);
}
(this.downimg ) zip;
}catch(err ) {
控制台. log (' err ',err );
}
(,
在本例中,您将使用async/await执行文件异步操作,以便在zip输入操作完成后执行zip下载。
downimg(zip ) {
zip
. generateAsync({ (
type:'blob'} )
. then(content={
let fileName='批量下载. zip ';
filesaver.saveas(content,fileName );
);
、//****传递图像链接并返回base64数据
获取基础64 image (URL ) returnnewpromise () resolve,reject ) )={var base64=' '; var img=newImage (;
img.setattribute('crossorigin ',' Anonymous ' );
img.() nl ) ad=)={
base64=this.image2base64(img;
解决(base64.split (',') ) [1];
(;
img.() nerr ) r=)=reject (“加载失败”);
//这里可能存在跨域失败的问题。 解决方案同上,url随机数
img.src=url;
);
(,
image2base64(img ) var canvas=document.createelement (' canvas );
canvas.width=img.width;
canvas.height=img.height; varCTX=canvas.getcontext('2d );
CTX.drawimage(img,0,0,img.width,img.height ); vardata URL=canvas.todataurl (image/png ); 返回数据URL;
、传递指向//****文件的链接并返回阵列缓冲器数据
获取文件(URL )返回新promise ) () resolve,reject )={
//这里的$http是Vue的axiosthis.$http({ (
方法: ' get ',
链接,
响应类型: '阵列缓冲器' } )
. then(data={
解决(data.data );
() )
. catch(error={
reject(pdf加载失败。 )错误);
);
);
(,
以上,实现了方式记录。