最近产品迭代了一个需求,之前项目中有个pdf文件下载的功能要根据ui的设计,来实现pdf文件样式。
这个需求后端老哥折腾了几天之后,样式最终也没有得到ui,产品,测试的满意。由于之前项目中的pdf下载基本上都是后端老哥来用模板完成,一时之间也没有想着用前端来实现。
起初想着用htmlToCanvas+pdfJs来实现,但是pdf的样式和页面的样式不一致,并且靠截图生成的pdf一些分页截断的问题处理起来也比较麻烦。后面找了一圈,发现了pdfmake这个好东西,文档链接贴出来:pdfmake
pdfmake就是根据配置一个json格式的pdf描述对象,然后通过里面的createPdf api来完成pdf的制作,但是默认的pdfmake不支持中文。
使用步骤:
1.使用vue-cli初始化一个项目;
2.安装依赖 :
npm install pdfmake
3.进入node_modules,并找到pdfmake目录,并在此目录下创建examples目录,再在examples目录里面创建fonts的子目录:
4.进入我的电脑,C:\Windows\Fonts 找到想要的中文字体,,复制粘贴到fonts文件夹下;
5.打开node_modules的pdfmake文件夹的终端,运行
node build-vfs.js "./examples/fonts"
6.在build文件夹下会生成vfs_fonts.js文件,这就是你刚刚复制进去的字体文件;
7.如何在页面使用:
<template>
<div @click="downLoadPdf" class="hello">
下载pdf
</div>
</template>
<script>
import {defineComponent} from "vue";
// 在项目里引入pdfmake
import pdfMake from "pdfmake/build/pdfmake";
import pdfFonts from "pdfmake/build/vfs_fonts";
pdfMake.vfs = pdfFonts.pdfMake.vfs;
pdfMake.vfs = pdfFonts.pdfMake.vfs;
// 定义字体
pdfMake.fonts = {
// webfont是字体名,可以自定义,下面需要用这个名字配置字体
webfont: {
// simhei.ttf 这个文件已经在 我们生成的 vfs_font.js 文件中,且已经引入,所以可以直接使用
//这里的字符串字体名称实际上映射的是node_modules里examples/fonts里对应的文件名
normal: "simhei.ttf",
bold: "simhei.ttf",
italics: "simhei.ttf",
bolditalics: "simhei.ttf",
},
// 可以定义多个字体
anotherFontName: {
},
};
// 下面我们来定义 pdfmake需要用的 pdf文件描述对象
// 这个描述对象 具体的字段可以参考官方文档
// 下面我们来定义 pdfmake需要用的 pdf文件描述对象
// 这个描述对象 具体的字段可以参考官方文档
var docDefinition = {
pageMargins: [ 40, 60, 40, 60 ],
content: [
{text: 'csdn《pdfmake小尝》', headlineLevel: 1,},
],
images: {
snow: 'https://picsum.photos/seed/picsum/200/300',
strawberries: {
url: 'https://picsum.photos/id/1080/367/267',
headers: {
myheader: '123',
myotherheader: 'abc',
}
}
},
background: function(currentPage, pageSize) {
if(currentPage===1){
return {
image:'snow',
width: pageSize.width,
height: pageSize.height
}
}
},
pageSize: 'A4',
defaultStyle: {
// 设置我们定义的字体为默认字体
font: "webfont",
},
footer: function(currentPage, pageCount) { if(currentPage===1){return null}return currentPage.toString() + ' of ' + pageCount; },
header: function(currentPage, pageCount, pageSize) {
// you can apply any logic and return any valid pdfmake element
if(currentPage===1){return null}
return [
{ text: 'simple text', alignment: (currentPage % 2) ? 'left' : 'right' },
{ canvas: [ { type: 'rect', x: 170, y: 32, w: pageSize.width - 170, h: 40 } ] }
]
},
};
export default defineComponent(
{
name: 'HelloWorld',
props: {
msg: String
},
setup(){
function downLoadPdf(){
console.log('xiazai')
pdfMake.createPdf(docDefinition).download("文件名", () => {
console.log("complete");
});
}
return {
downLoadPdf
}
}
}
)
</script>
8.效果: