当前位置: 首页 > Web前端 > JavaScript

网页中canvas预览的pdf打印解决方案

时间:2023-03-26 22:59:33 JavaScript

网页中canvas预览的pdf打印解决方案在日常生活中,总是需要借助搜索引擎来检索一些pdf文档。许多网站通常使用pdf文档预览,并且有禁止打印的限制。如果选择手动复制单张图片或剪切长图,免费难度大、费力。本文主要使用油猴脚本代码打印网页并生成pdf。文中的pdf打印思路用于前端学习。网页预览pdf的常见方式1.包含源地址的网页第一种pdf预览网站直接在前端html中包含了pdf文件的源地址。最常见的方式是在页面中嵌入iframe、embed、object标签,标签中会直接包含pdf的源地址。这种网站只要用f12查看元素就可以直接使用源地址pdf下载得到原始pdf文档。有的网站使用类似jquery.media.js的jquery插件来预览pdf,但这种方式还是把pdf的源地址写在了前端网页中。对于这种方法,可以通过在F12审查元素中搜索关键字.pdf来判断2.网页中没有包含pdf源地址第一种预览PDF的方式,通常是针对打开的PDF文档。对于一些下载量有限的文档预览网站,他们不会直接把PDF的源地址放到前端代码中。绘制画布以显示整个pdf文档。许多允许预览pdf的图书馆通常使用这种方式来显示文档。或者使用样式中background-image中的url属性放置图片地址。

或者使用画布绘制a逐页pdf文档如下图所示:预览这种形式的pdf,可以选择手动逐页截图整理成文档,不过最方便的方法肯定是ctrl+p打印网页,如果能去掉一些不需要的将侧边栏等不需要的部分打印成pdf是最完美的选择,但现实是残酷的。网页会温馨提示您,该页面禁止打印,或只能打印空白页,那是因为网站不支持打印而作了限制。使用外部js脚本打印pdf1。篡改猴脚本(Tampermonkey)是一个非常流行的浏览器扩展,可以运行社区编写的扩展脚本来实现各种功能,比如常见的移除广告、修改样式文件,甚至下载视频。其实油猴脚本可以在网页加载完成后再次加载你个人的js脚本,js可以控制整个网页文档的dom元素。您可以控制有关这些元素的一切,以实现您想要的功能。OilMonkey脚本可以安装在主流浏览器上。Google浏览器和firebox浏览器可以直接在应用商店搜索下载。谷歌浏览器也可以离线安装。不知道怎么安装的同学可以百度一下!!2.解锁打印设置禁止打印的表现形式可以多样化,可以把你的打印快捷键ctrl+p砍掉,但是大部分网页主要是通过@media属性来限制打印功能,完全禁止打印比较麻烦.所以只要用户打印的内容为空,就可以实现限制打印的功能。这里以百度文库为例,通过F12调出调试工具,然后在控制台输入代码window.print(),按下进入。网页打印出来了,但是发现整个文档的内容都是空的。这是因为网页中使用了@media来限制用户打印内容的输出。这时候可以加入一部分代码内容再次打印varstyle=document.createElement('style');style.innerHTML="@mediaprint{body{display:block}@page{margin:0;size:500px500px;}";window.document.head.appendChild(style);窗口打印();这里的代码内容其实就是嵌入了一个@media打印样式,可以覆盖之前禁止打印的样式,此时可以打印,但是会有很多扰人的内容,最重要的pdf内容是缺失,那是因为网页前面有很多@media内容,我们只是简单的打印body的样式时修改,而没有对其他元素进行任何操作。3.编写脚本经过刚才的操作步骤,我们可以简单的模拟一下编写脚本打印pdf的思路。首先,打印的时候打印的是整个网页,而我们需要的内容只是每一页的pdf信息,所以我们大胆的想出了一个思路,先获取网页中所有的pdf图片,只需要记录真实地址即可图片的。得到所有pdf页面后,我们直接清空body标签下的所有内容,然后一页一页重新放我们的pdf,然后打印这一页,得到整个pdf内容。在库页面打开油猴插件,点击添加脚本,在里面编辑我们个人的脚本代码。这里可以导入jquery库,方便使用jquery操作dom元素。//@requirehttp://code.jquery.com/jquery-1.11.0.min.js我们先用jquery逐级获取元素的background-image属性,然后用字符替换提取url("image_url")我们简单的用一个数组来存放所有图片的地址。为了规范以后打印的纸张,我们在获取图片地址的同时记录图片的长宽数据。letimgs=[]letimg_width=0;letimg_height=0;$('#reader-containerdiv.reader-pic-layer.ie-fix').each(function(){letcur_element=$(this).children('.reader-pic-item:last');让img_url=$(cur_element).css('backgroundImage');img_width=parseInt($(cur_element).css('width'));img_height=parseInt($(cur_element).css('height'));imgs.push(img_url.replace('url("','').replace('")',''));})console.log(img_width,img_height);控制台日志(imgs);Output查看数组中存放图片的地址,确认地址正确。但是我们不能让脚本直接触发,我们先创建一个按钮,点击按钮后触发后续操作。所以我们创建按钮元素并给它一个点击事件。letbtn=$('');$('body').append(btn);$(btn).on('click',function(){letimgs=[]letimg_width=0;letimg_height=0;$('#reader-containerdiv.reader-pic-layer.ie-fix').each(function(){letcur_element=$(this).children('.reader-pic-item:last');让img_url=$(cur_element).css('backgroundImage');img_width=parseInt($(cur_element).css('width'));img_height=parseInt($(cur_element).css('height'));imgs.push(img_url.replace('url("','').replace('")',''));})console.log(img_width,img_height);console.log(imgs);})这样,我们点击继续阅读,点击我们创建的下载按钮后,就会输出所有的pdf图片页面。这时我们已经输出了所有的pdf页面。现在我们只需要清空页面,然后简单的放pdf页面,然后触发浏览器页面的打印即可。在代码中,我们每次都需要创建一个img元素,并将其src属性设置为数组中存放的图片地址。同时需要给body设置一个以纵轴方向为中心的flex布局,让每个pdf页面都和普通pdf保持一致。代码如下$('body').empty();$('body').css('display','flex');$('body').css('flex-direction','column');for(leti=0;i')$(img).attr('src',imgs[i]);$('body').append(img);}此时页面只有我们的pdf页面,最后我们进行打印操作。这时候我们需要在@media中设置页面纸张大小,利用之前存储的图片的长宽数据来设置纸张大小。代码如下:varstyle=document.createElement('style');style.innerHTML="@mediaprint{body{display:block}@page{margin:0;size:"+img_width+"px"+img_height+"px;}";window.document.head.appendChild(style);window.print();写代码是为了写这篇文章,主要是为了体现实验思路,对很多人来说并不通用不同的页面,很多地方缺少考虑,最终实现效果如下:温馨提示(需要在整个页面加载完成后触发打印),最后把整个代码贴在这里,@match是为了满足匹配的url,而这个油猴脚本就会生效。//==UserScript==//@nameprint_pdf//@namespacehttp://tampermonkey.net///@version0.1//@descriptiontrytotakeovertheworld!//@authorYou//@matchhttps://wenku.baidu.com/view/6cc589a2872458fb770bf78a6529647d272834ac?fr=unit_43520_plan_3938_slotid_47//@iconhttps://www.google.com/s2/favicons?domain=baidu.com//@requirehttp://code.jquery.com/jquery-1.11.0.min.js//@grantnone//==/UserScript==(function(){'usestrict';letbtn=$('');$('body').append(btn);$(btn).on('click',function(){letimgs=[]letimg_width=0;让img_height=0;$('#reader-containerdiv.reader-pic-layer.ie-fix').each(function(){letcur_element=$(this).children('.reader-pic-item:last');让img_url=$(cur_element).css('backgroundImage');img_width=parseInt($(cur_element).css('width'));img_height=parseInt($(cur_element).css('height'));imgs。push(img_url.replace('url("','').replace('")',''));})console.log(img_width,img_height);控制台日志(imgs);$('正文').empty();$('body').css('显示','flex');$('body').css('flex-direction','column');for(leti=0;i')$(img).attr('src',imgs[i]);}$('正文').append(img);}//进行打印varstyle=document.createElement('style');style.innerHTML="@mediaprint{body{display:block}@page{margin:0;size:"+img_width+"px"+img_height+"px;}";window.document.head.appendChild(style);window.print();})})();总结整篇文章是为了提供一个禁止打印的思路,整个思路是从前端js方向出发,方法不高明,但是简单易行。封装,构造请求,不过应该会遇到加密数据。一些网页可能不会把所有的图片放在url中,也可能是通过动态增删元素实现的预览,不同的网站有很好的做法,不同的是,如果你想写出一个通用性强的好插件,你的代码需要有很强的适用性,除了图片存储,还有利用vanvas元素绘制一页一页的pdf,遇到这种形式,不能简单的存储源地址,这里提供一个思路,复制整个canvas元素到数组。函数save_canvas(oldCanvas){letnewCanvas=$('')[0];letnewCanvasContext=newCanvas.getContext('2d');//console.log(oldCanvas);newCanvas.width=oldCanvas.width;newCanvas.height=oldCanvas.height;newCanvasContext.drawImage(oldCanvas,0,0,oldCanvas.width,oldCanvas.height);returnnewCanvas;}文章用于记录学习。----东湖大白鹅