web开发HTML生成PDF的三种解决方案(服务器端mpdf、html2canvas.js、浏览器打印、PDF虚拟打印机)

简介: web开发HTML生成PDF的三种解决方案(服务器端mpdf、html2canvas.js、浏览器打印、PDF虚拟打印机)

前言

在web网页中加载并显示PDF文件是最常见的业务需求,目前浏览器大多数都自带pdf预览功能,但是每个浏览器的pdf加载器并不一样,工具栏也无法定制化。为了统一不同浏览器pdf预览的一致性,并增加一些自定义功能,需要在实际的项目开发过程中根据不同的情况进行pdf文档的生产。


一、服务器端生成PDF

mPDF是一个PHP类库,它由UTF-8编码的HTML生成PDF文件。它基于FPDF和HTML2FPDF ,再此基础上添加了许多功能。同时对css支持能力得到了大的提升,支持css样式的引入。mPDF生成类库的步骤如下:

1.开发对应HTML页面

如公开地址:http://test.com/index.php?m=Index&a=projectTable&act=showTable&zp_id=2

2.curl对应的HTML页面

/*
 1. 爬取
 2. $url,服务器地址;
 3. $header,文件头;
 4. $data,数据,array();
*/
function get_url($url)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    /*自适应SSL证书*/
    if (1 == strpos("$" . $url, "https://")) {
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    }
    $response = curl_exec($ch);
    curl_close($ch);
    return $response;
}


3.生成PDF文档

/*打印PDF详情页
 5. $url, 域名;
 6. $pro_id, 项目Id;
 7. $pro_types,机构类型;
 8. $waterMark,水印文字;
 9. $pro_serial,项目编号;
*/
function printPdf($url, $zp_id, $user_name, $waterMark)
{
    require_once("libs/mpdf/mpdf.php");
    $mpdf = new mPDF('utf-8', 'A4', '', '宋体', 0, 0, 20, 10);
    //$mpdf->shrink_tables_to_fit = 0;
    //添加水印;
    $mpdf->SetWatermarkText($waterMark, 0.1);//水印文字,透明度
    $mpdf->showWatermarkText = true; //开启水印
    if (preg_match("/([\x81-\xfe][\x40-\xfe])/", $waterMark, $match)) {
        $mpdf->watermark_font = 'GB';
    }
    //获取内容;
    $mpdf->useAdobeCJK = true;
    $html = get_url($url . '?m=Index&a=projectTable&act=showTable&zp_id=' . $zp_id);
    //设置PDF页眉内容
    //$header = '<table width="95%" style="margin:0 auto;border-bottom: 1px solid #4F81BD; vertical-align: middle; font-family:serif; font-size: 9pt; color: #000088;"><tr><td width="10%"></td><td width="80%" align="center" style="font-size:16px;color:#A0A0A0"></td><td width="10%" style="text-align: right;">山东精品课程申报系统</td></tr></table>';
    //设置PDF页脚内容
    $footer = '<table width="100%" style="vertical-align: bottom; font-size: 9pt; color: #000;"><tr style="height:30px"></tr><tr><td width="10%"></td><td width="80%" align="center" style="font-size:14px;color:#000"></td><td width="10%" style="font-size:14px;color:#000;">页码: {PAGENO} / {nb}</td></tr></table>';
    //添加页眉和页脚到pdf中
    //$mpdf->SetHTMLHeader($header);
    $mpdf->SetHTMLFooter($footer);
    //设置pdf显示方式
    $mpdf->SetDisplayMode('fullpage');
    //创建pdf文件
    $mpdf->WriteHTML($html);
    //输出pdf
    $mpdf->Output($user_name . '.pdf', 'I');//'D';下载模式
    exit;
}


4.注意事项

在读取html文档时,一般可以使用file_get_contents函数,但是如果访问量过大时,会造成CPU负荷多大,导致服务器宕机;

通过curl封装get_url($url)函数,在一定的程度上解决CPU负荷的问题;

如果爬取的文档内容不多,最彻底的解决方案:是在printPdf($url, $zp_id, $user_name, $waterMark)函数中做HTML和PHP混排;

生成的内容是文字,可以复制;

爬取内容时,如果对应的页面有用户登录权限,必须赋权访问,如:CURL获取cookies模拟登录的方法;

mpdf在自动分页上有很明显的优势,但在使用table布局时,大段落文字会出现压缩的情况,建议使用div布局。


二、html2canvas.js库

1.引入库html2canvas库

    <script type="text/javascript" src="static/rooted/js/html2canvas.min.js"></script>
    <script type="text/javascript" src="static/rooted/js/jspdf.min.js"></script>
    <script type="text/javascript" src="static/rooted/js/h2pdf.js"></script>


2.设置页面大小尺寸

案例默认使用A4大小。

/*表格打印*/
.page_width {
    width: 595.32pt;
}
.page {
    position: relative;
    margin: 0 auto;
}
#printId {
    width: 98%;
    height: 720pt;
    background: #FFF;
    color: #000;
    font-size: 16px;
}
/*控制表格内容宽高,防止被拉伸*/
.content_p {
    text-align: center;
    padding-top: 5px;
}
.content_p > table {
    width: 98%;
}
td {
    height: 30px;
    padding: 5px;
}
.title_td {
    font-weight: bold;
    text-align: center;
}
.verimg {
    position: absolute;
    right: 0px;
    top: 10px;
    z-index: 9999;
    transform: rotate(30deg)
}


3.HTML布局

<div class="page page_width">
    <div id="printId">
        <div class="content_p" id="content_p">
            <table  align="center" border="1" cellpadding="0">
                <tr>
                    <td colspan="4" class="title_td" style="font-size: 32px;padding: 10px;">山东省中医临床优秀人才选拔考试准考证</td>
                </tr>
                <tr>
                    <td colspan="4" class="title_td">身份信息</td>
                </tr>
                <tr>
                    <td align="center">准考证号</td>
                    <td colspan="2" align="center">SDYX001</td>
                    <td rowspan="6" align="center"><img width="160" height="242" src="upload/2022-06/SDYX001.jpg"></td>
                </tr>
                <tr>
                    <td align="center">姓名</td>
                    <td colspan="2" align="center">介保良</td>
                </tr>
                <tr>
                    <td align="center">性别</td>
                    <td colspan="2" align="center">男</td>
                </tr>
                <tr>
                    <td align="center">职称</td>
                    <td colspan="2" align="center">执业医师</td>
                </tr>
                <tr>
                    <td align="center">身份证号</td>
                    <td colspan="2" align="center">******</td>
                </tr>
                <tr>
                    <td align="center">工作单位</td>
                    <td colspan="2" align="center">中医院</td>
                </tr>
                <tr>
                    <td colspan="4" class="title_td">考试安排</td>
                </tr>
                <tr>
                    <td class="title_td">考试科目</td>
                    <td class="title_td">考试时间</td>
                    <td class="title_td">考试地点</td>
                    <td class="title_td">考场/座号</td>
                </tr>                              
            </table>
        </div>
    </div>
</div>


4.下载PDF文档

<div class="print_btn">
    <button type="button" class="layui-btn layui-btn-normal" onclick='printOut("lockdatav")'>下载PDF文档</button>
    <a type="button" id="ps" class="layui-btn layui-btn-normal" href="?m=Index&a=ticket&act=exam" target="_blank">网页版打印</a>
</div>


5.封装事件函数

    var ps = document.getElementById('ps');
    function preview(id) {
        var sprnhtml = $('#' + id).html(); //获取区域内容
        var selfhtml = $('body').html(); //获取当前页的html, 用来恢复页面
        $('body').html(sprnhtml);
        window.print();
        $('body').html(selfhtml);
    }
    ps.onclick = function () {
        preview('content_p');
    }


6.注意事项

  • PDF在浏览器端生成,减少了对服务器的压力;
  • 生成的PDF实际上是canvas画布base64图片,文字无法复制;
  • 如果是多页时,实现分页比较麻烦。


三、PDF虚拟打印机

使用浏览器自带的PDF虚拟打印机将网页打印成PDF格式:


打开需要保存或打印成PDF的网页,然后右击鼠标选择“打印”,或者直接利用Ctrl+P快捷键进入打印页面。

在弹出的对话框中,选择“闪电PDF虚拟打印机”,再点击“打印”;

选择“PDF”即可,同时,还可以对其他选项进行修改,如文件名、导出路径等。

选择“导出”;

已经成功将网页打印成PDF格式了;

双击打开文件查看效果;


总结

在web端生成pdf时,三种方法针对不同的场景各有利弊。

@漏刻有时

相关文章
|
9月前
|
移动开发 数据挖掘 开发者
服务器发送事件(SSE)在现代Web开发中的关键作用
服务器发送事件(SSE)是HTML5标准协议,用于服务器主动向客户端推送实时数据,适合单向通信场景。相比WebSocket,SSE更简洁高效,基于HTTP协议,具备自动重连、事件驱动等特性。常见应用场景包括实时通知、新闻推送、数据分析等。通过Apipost等工具可轻松调试SSE,助力开发者构建高效实时Web应用。示例中,电商平台利用SSE实现秒杀活动通知,显著减少延迟并简化架构。掌握SSE技术,能大幅提升用户体验与开发效率。
|
11月前
|
Web App开发 编解码 vr&ar
使用Web浏览器访问UE应用的最佳实践
在3D/XR应用开发中,尤其是基于UE(虚幻引擎)开发的高精度场景,传统终端因硬件局限难以流畅运行高帧率、复杂效果的三维应用。实时云渲染技术,将渲染任务转移至云端服务器,降低终端硬件要求,确保用户获得流畅体验。具备弹性扩展、优化传输协议、跨平台支持和安全性等优势,适用于多种终端和场景,特别集成像素流送技术,帮助UE开发者实现低代码上云操作,简化部署流程,保留UE引擎的强大开发能力,确保画面精美且终端轻量化。
491 17
使用Web浏览器访问UE应用的最佳实践
|
人工智能 前端开发 计算机视觉
Inpaint-Web:纯浏览器端实现的开源图像处理工具
在刷短视频时,常看到情侣在景区拍照被路人“抢镜”,男朋友用手机将路人“P”掉,既贴心又有趣。最近我发现了一个纯前端实现的开源项目——inpaint-web,可在浏览器端删除照片中的部分内容,非常酷。该项目基于 WebGPU 和 WASM 技术,支持图像修复与放大,已在 GitHub 上获得 5.1k Star。项目地址:[GitHub](https://github.com/lxfater/inpaint-web)。
762 3
 Inpaint-Web:纯浏览器端实现的开源图像处理工具
|
存储 缓存 前端开发
Web端IM聊天消息该不该用浏览器本地存储?一文即懂!
鉴于目前浏览器技术的进步(主要是HTML5的普及),在Web网页端IM聊天应用的技术选型阶段,很多开发者都会纠结到底该不该像原生移动端IM那样将聊天记录缓存在浏览器的本地,还是像传统Web端即时通讯那样继续存储在服务端?本文将为你简洁明了地讲清楚浏览器本地存储技术(Web Storage),然后你就知道到底该怎么选择了。
348 1
|
移动开发 前端开发 JavaScript
HTML5 浏览器支持1
现代浏览器普遍支持HTML5,但早期浏览器可能不支持。可以通过将HTML5元素定义为块级元素,使旧版浏览器也能正确显示。例如,可以使用CSS将header、section等8个新的HTML5语义元素设置为块级元素。此外,还可以通过JavaScript为HTML添加新的自定义元素,如使用`document.createElement(&quot;myHero&quot;)`为IE浏览器添加新元素。
|
XML 前端开发 JavaScript
PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑
本文深入探讨了PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑;Ajax则通过异步请求实现页面无刷新更新。文中详细介绍了两者的工作原理、数据传输格式选择、具体实现方法及实际应用案例,如实时数据更新、表单验证与提交、动态加载内容等。同时,针对跨域问题、数据安全与性能优化提出了建议。总结指出,PHP与Ajax的结合能显著提升Web应用的效率和用户体验。
308 3
|
Java PHP
PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。理解其垃圾回收机制有助于开发高效稳定的PHP应用。
【10月更文挑战第1天】PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。其垃圾回收机制包括引用计数与循环垃圾回收,对提升应用性能和稳定性至关重要。本文通过具体案例分析,详细探讨PHP垃圾回收机制的工作原理,特别是如何解决循环引用问题。在PHP 8中,垃圾回收机制得到进一步优化,提高了效率和准确性。理解这些机制有助于开发高效稳定的PHP应用。
182 3
|
存储 移动开发 前端开发
|
Web App开发 安全 网络安全
tplink虚拟服务器设置方法
为了更全面地理解云服务及其在企业应用中的角色,推荐访问,他们提供了一系列高性能、安全稳定的云服务器解决方案,包括但不限于香港云服务器、高防服务器等,特别适合寻求全球化业务扩展的企业。蓝易云不仅拥有全球化的基础设施布局,还提供针对各种行业定制的全栈云解决方案,助力企业实现云端部署,跨越传统界限,即刻启航云端之旅。
743 0
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
993 1