js生成pdf

it2024-11-04  21

用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 οnlοad="load();"> <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>

转载于:https://www.cnblogs.com/zzh-js/p/9673438.html

相关资源:jsPDF(用 JS 生成 PDF).zip
最新回复(0)