用js生成PDF的方案

在java里,我们常用Itext来生成pdf,在pdf文件里组合图片,文字,画表格,画线等操作,还会遇到中文支持的问题。

那好,现在想直接在web前端就生成pdf怎么办,目前有以下几个解决方案

1:JSPDF.js

这个库支持不同类型的PDF文件格式,包括:文本,数字,图形,图片,同时你可以自由的编辑标题或者其它类型元素。

还支持互动的内容制作,例如,你可以输入文字或者数字,然后jsPDF帮助生成最后的PDF内容。

缺点,不支持中文,不支持svg导入(解决方案:svg+html转换成canvas)

http://jspdf.com/

示例代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> 
<head> 
<title>Downloadify</title> 
<meta http-equiv="content-type" content="text/html;charset=utf-8"> 
<style type="text/css" media="screen"> 
body {background: #fff; width: 500px; margin: 20px auto;} 
input, textarea, p { font-family: 宋体, 黑体; font-size: 12pt;} 
input, textarea { border: solid 1px #aaa; padding: 4px; width: 98%;} 
</style> 
<script type="text/javascript" src="js/swfobject.js"></script> 
<script type="text/javascript" src="js/downloadify.js"></script> 
<script type="text/javascript" src="js/jspdf.js"></script> 
<!-- <script type="text/javascript" src="js/downloadify.min.js"></script> --> 
<script type="text/javascript"> 
window.load=function(){ 
Downloadify.create(‘downloadify‘,{ 
filename: function(){ 
return document.getElementById(‘filename‘).value; 
}, 
data: function(){ 
var doc = new jsPDF(); 
doc.text(20, 20, document.getElementById(‘data‘).value); 
doc.addPage(); 
doc.text(20, 20, document.getElementById(‘data‘).value); 
return doc.output(); 
}, 
onComplete: function(){ alert(‘成功保存文件!‘); }, 
onCancel: function(){ alert(‘您已经取消保存文件‘); }, 
onError: function(){ alert(‘出现错误了‘); }, 
swf: ‘js/downloadify.swf‘, 
downloadImage: ‘js/download.png‘, 
width: 100, 
height: 30, 
transparent: true, 
append: false 
}); 

</script> 
</head> 
<body > 
<input type="text" name="filename" value="文件名.pdf" id="filename" /><br /> 
<textarea cols="60" rows="10" name="data" id="data">it seem do not support to Chinese</textarea> 
<p id="downloadify">You must have Flash 10 installed to download this file.</p> 
</body> 
</html>

2:pdfmake

pdfmake的基本使用方法

1.包含以下两个文件


1

2

<script src="build/pdfmake.min.js"></script>

 <script src="build/vfs_fonts.js"></script>

2.在JS代码中声明一个Document-definition对象,这个是pdfmake自己的术语。简单点说,就是创建一个至少包含content属性的对象。然后就可以调用pdfMake的方法导出PDF,具体见如下代码:


1

2

3

4

5

6

7

8

9

10

11

<script type="text/javascript">

 //创建Document-definition对象 

 var dd = {

      content: [

       ‘One paragraph‘,

       ‘Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines‘

       ]

    };

 //导出PDF

 pdfMake.createPdf(dd).download();

 </script>

pdfmake支持中文

三个步骤:

1.到pdfmake项目网站,把工程都下载下来,然后进入工程目录将字体文件(比如微软雅黑.ttf)放到examples/fonts目录下,然后使用grunt dump_dir生成新的vfs_fonts.js文件;

从上面描述可知该工程是通过grunt管理的,如果无相关知识,请上网先补习下。

grunt dump_dir命令会将fonts目录下所有文件都打包,因此无用文件请别放进去。

微软雅黑.ttf网上一搜一大把,WINDOWS电脑系统盘下存放字体的目录也找得到。

2.回到自己的例子代码中,JS代码中修改pdfMake的fonts对象,声明当前要用到字体:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

pdfMake.fonts = {

     Roboto: {

       normal: ‘Roboto-Regular.ttf‘,

       bold: ‘Roboto-Medium.ttf‘,

       italics: ‘Roboto-Italic.ttf‘,

       bolditalics: ‘Roboto-Italic.ttf‘

     },

     微软雅黑: {

       normal: ‘微软雅黑.ttf‘,

       bold: ‘微软雅黑.ttf‘,

       italics: ‘微软雅黑.ttf‘,

       bolditalics: ‘微软雅黑.ttf‘,

     }

   };

3.Document-definition对象中声明默认要使用的字体,具体来说:就是声明一个对象,除了content属性,还要有一个defaultStyle属性,该defaultStyle下面还有再有一个font属性:


1

2

3

4

5

6

7

8

9

var dd = {

      content: [

       ‘中英文测试‘,

       ‘Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines‘

       ],

       defaultStyle: {

         font: ‘微软雅黑‘

       }

    };

以下为根据如上步骤做的一个完整例子源码:

<!DOCTYPE html>

<html lang="zh-CN">

  <head>

  <meta charset="utf-8">

  <title>my first export PDF</title>

  <script src="build/pdfmake.min.js"></script>

  <script src="build/vfs_fonts.js"></script>

  <script>

  function down() {

    var dd = {

      content: [

       ‘中英文测试‘,

       ‘Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines‘

       ],

       defaultStyle: {

         font: ‘微软雅黑‘

       }

    };

    pdfMake.fonts = {

      Roboto: {

        normal: ‘Roboto-Regular.ttf‘,

        bold: ‘Roboto-Medium.ttf‘,

        italics: ‘Roboto-Italic.ttf‘,

        bolditalics: ‘Roboto-Italic.ttf‘

      },

      微软雅黑: {

        normal: ‘微软雅黑.ttf‘,

        bold: ‘微软雅黑.ttf‘,

        italics: ‘微软雅黑.ttf‘,

        bolditalics: ‘微软雅黑.ttf‘,

      }

    };

    pdfMake.createPdf(dd).download();

  }

  </script>

  </head>

  <body>

  <button onclick="down()">下载</button>

  </body>

</html>

插入图片

在插入图片方面,jsPDF要求先将图片转换成Data URL才行,而pdfmake允许直接指定路径,看起来是很方便,但这是有条件的,必须是以node.js作为服务器,或者将图片放到vfs_fonts.js中,所以总的来说,用处不大,还是一样得将图片转换成Data URL形式才行。

为解决此问题,我写了一个ImageDataURL的函数对象,可同时传入多个图片地址。在图片都加载完成后,ImageDataURL.oncomplete将被触发,在回调中通过this.imgdata取出各个图片的Data URL,根据pdfmake的要求组织下,就可正确生成pdf了。

ImageDataURL的原理是通过H5的canvas标签,将图片绘制在canvas上,然后通过canvas的toDataURL得到图像的Data URL。使用时请注意浏览器兼容性问题。

以下为将sampleImage.jpg, sampleage.jpg, sampleImage.jpg依次写入PDF的例子,测试时sampleage.jpg不存在,PDF直接忽略。

<!DOCTYPE html>

<html lang="zh-CN">

  <head>

  <meta charset="utf-8">

  <title>my second export PDF</title>

  <script src="build/pdfmake.min.js"></script>

  <script src="build/vfs_fonts.js"></script>

  <script>

   

  function down() {

    var x = new ImageDataURL(["sampleImage.jpg""samplage.jpg""sampleImage.jpg"]);

    x.oncomplete = function() {

      var imgs = new Array();

      console.log("complete");

      for (key in this.imgdata) {

        if (this.imgdata[key] == this.emptyobj)//不存在的图片直接忽略

          continue;

        imgs.push({image:this.imgdata[key]});//pdfmake的图片格式{image:image dataurl}

      }

      var dd = {

        content: [

         ‘Title‘,

         imgs,

         ],

      };

      pdfMake.createPdf(dd).download();

    }

  }

  </script>

  </head>

  <body>

  <button onclick="down()">下载</button>

  <script>

  function ImageDataURL(urls) {//urls必须是字符串或字符串数组

    this.completenum = 0;

    this.totalnum = 0;

    this.imgdata = new Array();

    this.emptyobj = new Object();

    this.oncomplete = function(){};

    this.getDataURL = function(url, index) {

      var c = document.createElement("canvas");

      var cxt = c.getContext("2d");

      var img = new Image();

      var dataurl;

      var p;

      p = this;

      img.src = url;

      img.onload = function() {

        var i;

        var maxwidth = 500;

        var scale = 1.0;

        if (img.width > maxwidth) {

          scale = maxwidth / img.width;

          c.width = maxwidth;

          c.height = Math.floor(img.height * scale);

        else {

          c.width= img.width;

          c.height= img.height;

        }

        cxt.drawImage(img, 0, 0, c.width, c.height);

 

        p.imgdata[index] = c.toDataURL(‘image/jpeg‘);

        for (i = 0; i < p.totalnum; ++i) {

          if (p.imgdata[i] == null)

            break;

        }

        if (i == p.totalnum) {

          p.oncomplete();

        }

      };

      img.onerror = function() {

        p.imgdata[index] = p.emptyobj;

        for (i = 0; i < p.totalnum; ++i) {

          if (p.imgdata[i] == null)

            break;

        }

        if (i == p.totalnum) {

          p.oncomplete();

        }

      };

    }

    if (urls instanceof Array) {

      this.totalnum = urls.length; 

      this.imgdata = new Array(this.totalnum);

      for (key in urls) {

        this.getDataURL(urls[key], key);

      }

    else {

      this.imgdata = new Array(1);

      this.totalnum = 1;

      this.getDataURL(urls, 0);

    }

  }

 

  </script>

  </body>

</html>

引入依赖脚本

原理上需要先把需要保存的节点渲染到一个canvas,然后利用这个canvas制作pdf,所以先引入以下两个依赖代码文件:

<script src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.js"></script>
<script src="https://cdn.bootcss.com/jspdf/1.3.4/jspdf.debug.js"></script>
  • 1
  • 2

编写所需代码

假设所需要打印的dom的父容器的class名是right-aside,就可以写这样一个函数:

function () {
  var target = document.getElementsByClassName("right-aside")[0];
  target.style.background = "#FFFFFF";

  html2canvas(target, {
    onrendered:function(canvas) {
        var contentWidth = canvas.width;
        var contentHeight = canvas.height;

        //一页pdf显示html页面生成的canvas高度;
        var pageHeight = contentWidth / 592.28 * 841.89;
        //未生成pdf的html页面高度
        var leftHeight = contentHeight;
        //页面偏移
        var position = 0;
        //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
        var imgWidth = 595.28;
        var imgHeight = 592.28/contentWidth * contentHeight;

        var pageData = canvas.toDataURL(‘image/jpeg‘, 1.0);

        var pdf = new jsPDF(‘‘, ‘pt‘, ‘a4‘);

        //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
        //当内容未超过pdf一页显示的范围,无需分页
        if (leftHeight < pageHeight) {
        pdf.addImage(pageData, ‘JPEG‘, 0, 0, imgWidth, imgHeight );
        } else {
            while(leftHeight > 0) {
                pdf.addImage(pageData, ‘JPEG‘, 0, position, imgWidth, imgHeight)
                leftHeight -= pageHeight;
                position -= 841.89;
                //避免添加空白页
                if(leftHeight > 0) {
                  pdf.addPage();
                }
            }
        }

        pdf.save("content.pdf");
    }
  })
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

以上代码将会以a4纸的尺寸来生成pdf文件,可以分页,代码来自于网络!

坑点提示

jsPDF打印成pdf文件时,注意页面要回到打印区域的顶部,我在该demo设置了先回到页面顶部,再打印,这样就不会出现黑块了。

jsPDF打印成pdf文件时,注意设置打印区域dom的背景色为白色,即#FFFFFF

原文地址:https://www.cnblogs.com/Alex80/p/9105408.html

时间: 2024-10-23 03:38:39

用js生成PDF的方案的相关文章

js生成pdf报表

由于前台html已经动态生成报表,而且,前台有一个功能,一个date range组件,当你拖动的时候,报表会在不提交到后台的情况下动态变化.因此需要用到js生成生报表: 用到的组件: jquery.js jspdf.js canvg.js html2canvas.js jspdf.plugin.autotable.js 前台动态生成的chart现在一般是用的html5的canvas或者是svg,很不幸运,我遇到的是svg, 如果是flash没研究过.由于报表还需要保持原html页面的外观,但是又

JS生成PDF文件

代码: var pdf = new jsPDF('p','pt','a4'); pdf.internal.scaleFactor = 1; //可以调整缩放比例 var options = { //pagesplit: true //分页 pagesplit: false//不分页 }; //执行调用 //下面的0,0为截取的位置(默许为0,0) //$('.header .h1Title').text()为我自定义的标题,具体根据自身的项目来设置 pdf.addHTML($('.wrap').

生成PDF的几种方式

1.后台生成PDF thinkphp利用MPDF插件 示例代码: public function pdf(){ //引入类库 Vendor('mpdf.mpdf'); //设置中文编码 $mpdf=new \mPDF('zh-cn','A4', 0, '宋体', 0, 0); //html内容 $html='<h1><a name="top"></a>一个PDF文件</h1>'; $mpdf->WriteHTML($html); $

Gitbook 生成 pdf 中文字体错乱问题解决办法

Gitbook 生成 pdf 中文字体错乱问题解决办法 用过 Gitbook 的都知道, Gitbook 会自动生成 pdf 以提供下载, 但十分遗憾的是自动生成的 pdf 对中文的支持并不好, 经常出现字体不一致的现象, 影响阅读, 强迫症更是难以忍受. 示例: 下面针对这一问题提供简单的解决办法: 本地命令行生成 pdf 文件. 当然这种方法有一定局限性, 你需要找到托管在 github 对应的源码仓库且转换过程中不出错. (由于水平有限未能解决在线生成的pdf中文字体错乱问题, 见谅. 也

使用flying-saucer,利用HTML来生成PDF文件(裴东辉)

1.导入maven依赖 <flyingSaucer.version>9.1.0</flyingSaucer.version> <!-- flying-saucer --> <dependency>    <groupId>org.xhtmlrenderer</groupId>     <artifactId>flying-saucer-pdf</artifactId>     <version>${

使用webdriver + phantomjs + pdfkit 生成PDF文件

实例 #!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on Dec 6, 2013 @author: Jay <[email protected]> @description: use PhantomJS to parse a web page to get the geo info of an IP ''' import datetime import urllib # from pyquery import PyQuery as

Freemarker+IText生成pdf文件

最近项目中遇到要用html生成pdf文件的需求,一开始研究了下前端插件jspdf,使用h5 canvas绘图生成图片,再把图片生成pdf文件,遇到了各种各样的问题,生成的pdf文件达到20多M,height超过5000浏览器就崩溃,有兴趣的童鞋可以尝试一下,该方案LZ最终放弃了. 接着开始尝试服务端生成,使用freemaker模板生成静态html文件,通过iext生成pdf,网上很多关于renderer.setDocument(dom,null)的用法,LZ尝试后发现效率奇低,最后放弃了,直接使

在C#.NET中,如何生成PDF文件?主要有以下几个途径

1.使用.NET文件流技术:若通过.NET的文件流技术生成PDF文件,必须对PDF文件的语法很清楚,例如BT表示实体内容开始:ET表示实体内容结束:TD表示换行等等.我们可以从Adobe的官方网站上下载PDF的语法说明文档,但文档几乎有1000页.如果熟悉好语法以后再编程,花费的时间肯定很长,而且生成的PDF文档不一定能满足要求.有关C# 代码参见附件.有关PDF文件的语法详见:http://partners.adobe.com/public/developer/en/pdf/PDFRefere

js实现pdf对页面的打印

//-------------------------------点击打印的图标--------------------------------- <div class="dcsc"><img src="${rootUrl }images/pdf-icon.png" id="file_pdf_kong" class="center-block img-responsive" title="下载PDF