一、问题描述:
下载历史课堂板书原来是需要点图片一张张下载,比较麻烦;调整为把所有图片合并为pdf后下载。应用jsPDF插件,在移动端获取图片地址时,报跨域问题。
二、知识点补充:
1、jsPDF 是一个基于HTML5的客户端解决方案,用于生成各种用途的 PDF 文档。
1、安装:npm install jspdf
2、引入:import jsPDF from "jspdf"
3、使用:
let pdf = new jsPDF('p', 'pt', 'a4');
//第一个参数: l:横向 p:纵向
//第二个参数:测量单位("pt","mm", "cm", "m", "in" or "px")
//第三个参数:默认为“a4”。如果您想使用自己的格式,只需将大小作为数字数组传递,例如[595.28, 841.89];
4、常用方法
pdf.addPage() 在PDF文档中添加新页面:
readPDF.addPage([imgwidth,imgHeight], 'p')//参数:(尺寸大小:默认a4 , 方向l:横向 p:纵向)
pdf.addImage() 将图像添加到PDF:
readPDF.addImage(ImageDate, 'JPEG', posX, posY, imgWidth, imgHeight)//参数:(imageData,格式,开始坐标x,开始坐标y,宽,高)
pdf.save() 保存pdf文档
readPDF.save('板书.pdf')
三、问题梳理分析:
图片是来自于阿里云服务器的,跟访问的页面不是同一个域名,存在跨域的问题。这边有两个问题:
1、为什么图片在页面上能正常显示?
通过 dom 节点的 <img> 标签来直接访问是没有问题,因为浏览器本身不会有跨域问题。而图片再次被复用到 canvas 上去时,就报跨域错误。
2、为什么pc端没有问题?
pc端是electron框架内置chrome浏览器,关闭了跨域设置。移动端是通过webview访问,存在跨域问题。
如果是chrome环境,同样存在跨域问题。
四、解决方式:
图片增加crossOrigin属性
<img crossOrigin="anonymous"/>
pdf根据图片生成pdf时,创建image标签,给图片也加上crossOrigin属性
const img = new Image();
img.crossOrigin = 'anonymous';
加了 crossorigin 属性,则表明图片就一定会按照 CORS 来请求图片。而通过CORS 请求到的图片可以再次被复用到 canvas 上进行绘制。换言之,如果不加 crossorigin 属性的话,那么图片是不能再次被复用到 canvas 上去的。
什么是crossOrigin?
相较于anonymous,use-credentials 是加了证书的 CORS。
五、问题后续:
这种方式,可以解决新生成图片的跨域问题。对于用户以前访问过的图片,浏览器默认情况下会将其缓存起来。当我们从 JS 的代码中创建的 <img> 再去访问同一个图片时,浏览器就不会再发起新的请求,而是直接访问缓存的图片。而缓存中的图片是不带跨域头的,所以浏览器直接就拒绝了。
处理方式:
pdf生成图片时,使用时间戳去直接访问服务器资源,绕过访问浏览器缓存;至此问题彻底解决。
const img = new Image();
- img.src = src;
+ img.src = `${src}?${Date.now()}`;
img.crossOrigin = 'anonymous';
参考:
https://www.jianshu.com/p/8fa0fb53c183