在WEB上想做一个导出PDF的功能,发现jsPDF比较多人推荐,遗憾的是不支持中文,最后找到pdfmake,很好地解决了此问题。它的效果可以先到http://pdfmake.org/playground.html查看。在使用过程中,还发现图片的插入是相对繁琐的一件事。

针对这些问题,本文的主要内容可分为三部分:

  • pdfmake的基本使用方法;
  • 如何解决中文问题;
  • 如何通过指定图片地址插入图片。

pdfmake的基本使用方法

1.包含以下两个文件

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

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

 <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的完整教程请登陆pdfmake项目查看。

pdfmake支持中文

三个步骤:

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

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

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

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

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

        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属性:

        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>

参考

JS导出PDF插件(支持中文、图片使用路径)的更多相关文章

  1. tcpdf导出pdf数据支持中文的解决方案

    步骤如下:1.确保你测试tcpdf能正常输出英文内容的pdf2.测试输入中文内容后显示是?的乱码或者空白分析原因,是因为我们输入的中文,tcpdf字体库并不支持,因此乱码或者空白显示 添加一个合适的字 ...

  2. Jupyter Notebook 导出PDF与Latex中文支持

    Jupyter Notebook 最近搞机器学习用到了Jupyter Notebook. 作为一个实时记事本,有时需要将内容导出为PDF. 但是,Jupyter Notebook自带的File -&g ...

  3. iText导出pdf、word、图片

    一.前言 在企业的信息系统中,报表处理一直占比较重要的作用,本文将介绍一种生成PDF报表的Java组件--iText.通过在服务器端使用Jsp或JavaBean生成PDF报表,客户端采用超级连接显示或 ...

  4. Magento PDF发票,支持中文,以及修改的办法

    Magento PDF发票,支持中文,以及修改的办法.   如果让magento的PDF发票支持中文.Magento生成PDF发票.使用的是zend framework的zend_pdf类. 下面是一 ...

  5. PHP生成PDF完美支持中文,解决TCPDF乱码

    PHP生成PDF完美支持中文,解决TCPDF乱码 2011-09-26 09:04 418人阅读 评论(0) 收藏 举报 phpfontsheaderttfxhtml文档 PHP生成PDF完美支持中文 ...

  6. php导出pdf,dompdf中文字体乱码解决办法(特别是代码迁移引起的乱码)

    dompdf\lib\fonts\dompdf_font_family_cache.php记住这个文件里面存放的是字体生成的缓存,迁移时如果覆盖了这个文件会导致乱码而且很难找到出错的地方,相信我... ...

  7. 【原创】JavaFx程序解决Jupyter Notebook导出PDF不显示中文

    0.ATTENTION!!! JavaFx里是通过Java调用控制台执行的的jupyter和xelatex指令, 这些个指令需要在本地安装Jupyter和MikTeX之后才能正常在电脑上运行 1.[问 ...

  8. Redmine 甘特图导出 PDF 和 PNG 中文乱码问题

    Redmine使用了RMagick来处理图片,fpdf处理PDF,并在调用时设定了字体PDF中文字体 redmine 中关于PDF字体设置的代码 case pdf_encoding           ...

  9. 改造jQuery-Tagit 插件支持中文全角的逗号和空格

    jQuery 的 tagit 插件效果还是不错的,今天用到该插件但发现不能自定义标签分隔符,只能是英文半角逗号或空格,于是想改造下 效果: 先研究了一番插件的代码,发现并不能通过插件自身的扩展方法来实 ...

随机推荐

  1. html5 canvas 画图表

    (function () { var canvas = document.createElement("canvas"); canvas.width = 800; canvas.h ...

  2. C++ 面试 (1) 指针

    指针是C++中一类颇具特色的数据类型,允许直接操作内存地址,实现内存的动态分配.指针问题通常包括指针常量,常量指针,数组指针,指针数组,函数指针,指针传值等. 指针和引用的区别 非空区别.在任何情况下 ...

  3. Sql Server之使用T_SQL创建,修改,查看数据库信息

    一.使用Transact_SQL创建数据库 Transact_SQL语法如下:  create database database_name   [ on     [primary]  [<fi ...

  4. 3.Code-First 约定(EF Code-First系列)

    前面,我们已经了解了Code-First利用领域类,怎么为我们创建数据库的简单示例.现在我们来学习一下Code-First约定吧. 什么是约定 约定说白了,就是基于一套规矩办事,这里就是基于你定义好的 ...

  5. Windows 10 内置管理员无法打开Metro应用方法

    前言 在windows 10中,由于权限原因,使用了内置管理员账户.虽然这样权限获取了,但是不能打开Metro应用,Microsoft Edge浏览器等,有点不太好.那有没有方法可以修改呢?这是本文要 ...

  6. Python 3.4 Library setup

    matplotlib:  https://pypi.python.org/pypi/matplotlib/1.4.3 Unofficial Windows Binaries for Python Ex ...

  7. CORS(跨源资源共享)实战

    声明:本文中的cors为createCORSRequest返回的对象 1. 同一跨域接口 function createCORSRequest(method, url) { var xhr = new ...

  8. html页面内容超出后显示水平滚动条的问题

    这个问题已经遇到好几次,解决起来也熟练了很多.   出现这种问题一般都是html或页面中的某一内部元素宽度超了. 下面总结我遇到的几种情况: 1.某一内部元素width设为100%,然而它还有bord ...

  9. 【开发软件】推荐一款MAC OS X 下php集成开发环境mamp

      这里给大家推荐一款在mac上搭建WEB服务器环境的集成环境安装软件,非常的好用,需要的朋友可以拿去,不用谢 ^_^   之前苦于mac上搭建本地服务器之艰辛,找寻好久都没找到一款类似windows ...

  10. 能力素质模型咨询工具(Part1)

          之前写过由企业家基本素质想到的文章,里面提及一些能力与素质,以下有内容也可以参考: 领导职位 表6-1 远见卓识的行为表现 级 别 行 为 表 现 A (1)关注行业的前景和环境的变化, ...