乐趣区

关于javascript:前端生成PDF让后端刮目相看

PDF 简介

PDF 全称 Portable Document Format (PDF)(便携文档格局), 该格局的显示与操作系统、分辨率、设施等因素没有关系,不论是在 Windows,Unix 还是在苹果公司的 Mac OS 操作系统中 PDF 格局都通用。Adobe 公司在 1993 年为了文档传输发明了这个文件格式,这个格局应用 PostScript 页面描述语言,实用于列印图像和文字(无论是在纸、胶片或非物质的 CRT 都可)。PDF 是基于页面描述语言。它既能够像程序代码一样具备可读性,又能示意出可任意放大和放大的矢量图。

PDF 文件格式能够将文字、字型、格局、色彩及独立于设施和分辨率的图形图像等封装在一个文件中,该格式文件还能够蕴含超文本链接、声音和动静影像等电子信息,反对专长文件,集成度和平安可靠性都较高。

为什么 PDF 文件可能如此流行

很多人所吐槽,说 PDF 既不能编辑,也不好复制内容,更无奈间接转换成 Word,为什么要用 PDF 来传输材料呢?

殊不知,大家吐槽的毛病,正是因为它长处的过于弱小而引起的。

PDF 的产生之初的目标,是为了适应纸媒的印刷行业。PDF 本来并非为小屏幕电子浏览设计的文件规范,它来自于印刷——基于纸张大小进行的排版。咱们能够把它当成纸质文稿的电子化,非电子文本,而是电子化的印刷了货色的纸张。它存在的目标是为了实现批量精准的印刷,保障在多个屏幕,多个零碎,多终端中文件格式都能保留绝对地位,展现布局都不会呈现格局错乱,保障了打印到纸张上的格局完全一致,而不会内容格局面目而非。

试想,如果咱们须要打印一份保险认购书,保险业务人员应用 iPad 打印的 PDF 文件和应用 PC 电脑打印进去的文件格式相差很大,页数不统一,换行不统一,那到底如何保障保险认购书的法律效应呢。一份保单能够有多种格局,那就无奈信赖任何一份保单了。正如你背后有多个时钟,咱们也就无奈获取以后精确工夫。

如果你实现过相似于打印页面,打印表单等性能,你可能会深有体会这其中的坑,吃过的苦只有本人分明。

因为将网页保留为 PDF 让用户预览或下载不失为一种保障格局在各终端统一的好办法。

除此之外,PDF 的劣势除了跨平台,兼容性高,也 最大水平升高了查看老本,终端用户不须要装置一套惨重全功能的 Adobe 能力读到 PDF 文件,只有客户机器上有浏览器就能够查看 PDF 内容。这也就是终端用户无论是手机端 iOS, Android,还是老的 PC,新的 PC 机器都能够随时随地关上 PDF 文件,反对浏览的形式十分多样便捷,而不是像 Excel 文件必须要 office 才可能读取。

再加上 PDF 也能够进行小范畴的编辑,平安属性的设置,如加密,加密打印等性能,实用性也是回升到另一个档次。

前端生成 PDF 文件利用场景

随着挪动互联网的倒退,手机端增长需要暴增,互联网零碎越多越多,新型零碎都是为了更方便快捷解决用户而利用而生的,而用户需要也随着技术的倒退悄悄产生扭转。

“ 全民皆网民 ” 的阶段,再不是基本功能满足就能够站住脚的时代,用户体验及交互需要更加迫切,使得从机器时代的设计到人性化的设计,更加易用性。

前后端拆散的技术架构畅行,让业余的人做业余的事件,开发更加高效畅通,因而在前端生成和展现 PDF 文件的需要也是比拟广泛,咱们总结一下 PDF 的常见利用场景:

  1. 我的项目中预览 PDF 文件,并且提供搜寻能力
  2. 手机端预览 PDF 文件
  3. 用户填写表单,生成 PDF 文件,用户间接下载保留
  4. 线上生成 PDF 合同,打印

简略总结生成 PDF 的三类需要:

  1. 在线预览,间接关上现有的 PDF 文件进行浏览确认信息。
  2. 实现在线生成 PDF 文件,依据用户的上下文信息,如新提交的表单信息,客户信息,洽购信息等即时生成个性化的 PDF 文件,供用户查看或下载。
  3. 打印,将已有或已生成的 PDF 文件间接打印。

在前端生成 PDF 文件是十分广泛的需要,简直业务简单的零碎都会有这样的要求。

前端生成 PDF 文件难点

前端生成 PDF 文件的难点在于,前端纯依赖于客户端的浏览器资源,可用的资源有限度,终端多样性,导致生成 PDF 难度也比服务端减少了不少。以 ActiveReportsJS 前端报表控件为示例,它提供了前端的 PDF 导出能力,但在导出 PDF 文件之前,咱们须要留神以下几个问题:

  • ActiveReportsJS 组件是前端控件,整体运行都基于 Web 浏览器环境来运行。
  • 桌面报表设计器 是基于 Electron 应用 Chromium 来显示用户界面。
  • Web 在线设计器 和 报表 viewer 组件在用户计算机的浏览器中运行的 Web 应用程序。
  • PDF, Excel 和 HTML 作为生成器,基于浏览器环境来测量并生成报表内容。
  • 报表由文本内容组成,浏览器通过基于 glyphs(字形)来渲染的字体形态。字体资源蕴含将字符编码映射到代表这些字符的字形的信息。因而,浏览器须要拜访正确的字体资源,才可能依照预期显示文本。

因而在前端生成 PDF 有三座大山须要克服:

  • 浏览器。浏览器堪称百家齐鸣,不过当初的支流浏览器数量也还好,不过三四家而已,如 Chrome,FireFox,Safari,Edge,浏览器,当然还有国内称霸的 360 浏览器。每个浏览器对于文字内容,甚至 CSS 属性解决都不统一,而正因为各家有各家的规范,会呈现咱们在 Chrome 中能够失常应用所有性能,而火狐应用 PDF 时,内容无奈失常显示,但打印性能失常。
  • 分辨率。如果要列出天下所有的分辨率,恐怕一张 A3 纸都无奈齐全输入了,如果基于 Dom 渲染的网页,遇到分辨率差别大的终端,那么放大放大的问题齐全无奈解决。
  • 字体。英文和数字等 Unicode 字符都能够保障 PDF 失常显示,但如果页面中蕴含中文字符,在生成 PDF 时是基于字形绘制的,如果提供的字形与理论页面展现的字形不统一,那导致生成 PDF 并不是所见即所得的成果,可能对于一些格局要求比拟严格的文件,准确到换行字符,行数,边距等都会是灾难性问题,因而提供正确的字体也是 PDF 生成时,保障格局统一是最重要的一点。

罕用的前端生成 PDF 文件办法

办法一

html2canvas+ jsPdf 的办法将 HTML 转换成图片后,在将图转 PDF 文件

实用场景:实用单页 PDF 文件,且终端设备统一

示例代码:

HTML:

<html>

  <body>
    <header>This is the header</header>
    <div id="content">
      This is the element you only want to capture
    </div>
    <button id="print">Download Pdf</button>
    <footer>This is the footer</footer>
  </body>

</html>

CSS:

body {background: beige;}

header {background: red;}

footer {background: blue;}

#content {
  background: yellow;
  width: 70%;
  height: 100px;
  margin: 50px auto;
  border: 1px solid orange;
  padding: 20px;
}

JS:

$('#print').click(function() {var w = document.getElementById("content").offsetWidth;
  var h = document.getElementById("content").offsetHeight;
  html2canvas(document.getElementById("content"), {
    dpi: 300, // Set to 300 DPI
    scale: 3, // Adjusts your resolution
    onrendered: function(canvas) {var img = canvas.toDataURL("image/jpeg", 1);
      var doc = new jsPDF('L', 'px', [w, h]);
      doc.addImage(img, 'JPEG', 0, 0, w, h);
      doc.save('sample-file.pdf');
    }
  });
})


毛病:

  • 生成的 PDF 文件由图片形成,内容无奈拷贝,放大后不清晰
  • 分页打印地位无法控制

办法二

jsPDF 间接基于 Dom 对象生成 PDF 文件

jsPDF,反对增加页码

实用场景:适宜简略的页面布局,如惯例的二维表,但简单的报表款式定义 Dom 元素,应用起来就异样简单了。

<script>
    function demoFromHTML() {var pdf = new jsPDF('p', 'pt', 'letter');
        // source can be HTML-formatted string, or a reference
        // to an actual DOM element from which the text will be scraped.
        source = $('#content')[0];

        // we support special element handlers. Register them with jQuery-style 
        // ID selector for either ID or node name. ("#iAmID", "div", "span" etc.)
        // There is no support for any other type of selectors 
        // (class, of compound) at this time.
        specialElementHandlers = {
            // element with id of "bypass" - jQuery style selector
            '#bypassme': function (element, renderer) {
                // true = "handled elsewhere, bypass text extraction"
                return true
            }
        };
        margins = {
            top: 80,
            bottom: 60,
            left: 40,
            width: 522
        };
        // all coords and widths are in jsPDF instance's declared units
        // 'inches' in this case
        pdf.fromHTML(
        source, // HTML string or DOM elem ref.
        margins.left, // x coord
        margins.top, { // y coord
            'width': margins.width, // max width of content on PDF
            'elementHandlers': specialElementHandlers
        },

        function (dispose) {
            // dispose: object with X, Y of the last line add to the PDF 
            //          this allow the insertion of new lines after html
            pdf.save('Test.pdf');
        }, margins);
    }
 </script>

毛病:

  • 多平台之间展现有差别,如手机端展现的 Dom 构造和电脑端布局有很大不同
  • 对中日韩文的字体反对不佳,会呈现乱码
  • 布局在不同浏览器中有差别

办法三

应用 ActiveReportsJS 间接在线设计布局,并间接生成 PDF 文件

长处:简略易用,可视化操作,所见即所得,代码量少,实用于多平台,保障 PC 端,Web 端,手机端三端统一。

毛病:须要配相应字体,可能满足精准生成 PDF 的需要。实用于保险业,金融业,检测业等对于 PDF 文件格式要求严格的的行业。

字体信息通常蕴含:

  • 字体名称: 字体 ID 如 Arial,Calibri,或 Times New Roman
  • 字体款式: 失常 或 斜体
  • 字体粗细: 较细,细体,失常,适中,粗体,较粗
  • 字体系列通常由多个字体组成,通常由独自的文件示意。

接下来咱们一起来看看具体实现过程。

在报表 Viewer 中显示报表,将报表导出为 PDF 或托管报表设计器组件的应用程序应应用与为独立设计器应用程序创立的配置雷同的配置。最简略的形式是复制 Fonts 文件夹和 fontsConfig.json 文件到我的项目的 assets 文件夹上面. 此文件夹因不同的前端框架而异。示例如下:

RegisterFonts 办法是个异步函数,并会返回 Promise 对象。也能够调用此办法的代码能够期待,直到返回 Promise 后果后,再在查看器组件中加载报表或导出报表。

{
    "name": "Montserrat",
    "weight": "900",
    "style": "italic",
    "source": "assets/Fonts/Montserrat/Montserrat-BlackItalic.ttf"
}  

<script src="https://cdn.grapecity.com/activereportsjs/2.latest/dist/ar-js-core.js"></script>
<script>
  GC.ActiveReports.Core.FontStore.registerFonts("/resources/fontsConfig.json" // replace the URL with the actual one)
</script>  


var pageReport = new ARJS.PageReport();
            pageReport.load('Quotation.rdlx-json')
                .then(function() {return pageReport.run() })
                .then(function(pageDocument) {return PDF.exportDocument(pageDocument, settings) })
                .then(function(result) {result.download('arjs-pdf') });

HTML 展现效果图:

PDF 展现效果图:

参考示例:https://demo.grapecity.com.cn/activereportsjs/demos/api/export/purejs

本文为大家介绍了三种不同形式实现了各种 PDF 打印的形式,后续还会为大家带来更多乏味的内容~ 感觉不错点个赞再走吧

退出移动版