道客这样的文档网站,对于很多PDF都要求积分,积分不到不让下载。
这个不是很爽,因为我难得去上面下载一份找了半天的文档资料,还要我注册,注册了还不算还要我拼命赚积分,不赚积分就要充值,太恶劣了。
作为一个崇尚开源/自由的人——其实主要是我不舍得花钱,要想办法来解决这个问题。
这类PDF文档网站都提供文件的预览,甚至是全文预览,只不过下载的时候有积分这道坎。
而他们的全文预览,不是直接用的PDF,而是把PDF内容写入到Canvas中,而Canvas的内容不让下载。
既然是写入到Canvas中,那就由不得你不让我下载了。
下面是两个函数,专门处理这个问题:
var saveCanvas = (cvs, filename) => {
cvs.toBlob(blob => {
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = filename || 'canvas.png';
a.click();
});
};
var canvas2File = filename => {
filename = filename || 'canvasPDF';
var cvs = document.querySelectorAll('canvas');
[].forEach.call(cvs, (c, i) => {
saveCanvas(c, filename + '_' + (i + 1) + '.png');
});
}
思路其实很简单。
Canvas对象可以把其中的内容(无论是普通的2d的context,还是webgl或者webgl2)导出为blob(或者base64格式的dataURL)。
而后,window的URL组件可以将blob对象转化为可以用来下载或者让别的页面使用的objectURL(这个要注意,使用完以后要释放资源,不然内存就爆了),用来进一步给IMG或者BACKGROUNDIMAGE或者别的CANVAS使用,而且也可以用来作为link的目标对象。
这样,我们先把canvas内容转化为blob,然后再转化为objectURL,最后新建一个link,并模拟点击,从而实现自动下载。
这里还可以做得更加完善一点,那就是获取每个canvas的实际尺寸(canvas的获取context,而一个context带有实际绘制区的宽高属性),然后新建一个canvas将所有目标canvas的内容绘制到这个新的canvas上(注意上下衔接,使用context的height属性来往下移动并拼接),最后将这个新的canvas所谓真正要导出的目标,下载到本地。
这里就不给代码了。