pdfMake前端导出pdf

pdfMake前端导出pdf

目前导出PDF还是后端(或nodejs)比较好. (如果没有必要)

导出方案

后端: IText,wkhtmltopdf...等等.

前端: jsPdf,pdfKit,react-pdf...等等.

现在网上一提到前端导出pdf的绝大多数都是html2canvas + jspdf 实现html转pdf.这是非常棒的一个解决方案,不过它有一个弊端就是内容放大之后会失真.如果遇到这类需求就只能含泪放弃了.html2canvas主要解决的是jspdf中文乱码的问题,因为是外国小哥开发的,所以就没考虑过中文兼容.这些或多或少的pdf框架都有中文乱码的问题.

还有一种是pdfKit的二次封装 pdfMake .这也是我所采用的方案,相比较jspdf和pdfkit,使用起来更易上手.也有中文乱码的解决方案.github地址 官方网站

使用pdfMake

这里我又用到了webWorker,具体原因和配置我后面解释.

// UI线程--------------------------------------------
import Worker from './components/imppdf.worker.js';
let worker = new Worker(); // 传入 worker 脚本文件的路径即可
const 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: '方正姚体'
    }
};
worker.postMessage(dd);
worker.onmessage = function (event: any) {
  if (event.data?.type === "progress") {
    // 返回的进度信息0-1
  } else {
    const link = document.createElement("a");
    link.style.display = "none";
    link.href = URL.createObjectURL(event.data);
    link.setAttribute("download", decodeURI('下载.pdf'));
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };
}

// webWorker-----------------------------------------
import pdfMake from "pdfmake/build/pdfmake"; 
import FZvfs from "./FZYTvfs_fonts"; // .ttf字体文件打包后的js文件
pdfMake.vfs = FZvfs;
pdfMake.fonts = { // 添加字体库
  方正姚体: {
    normal: 'FZYTK.TTF',
    bold: 'FZYTK.TTF',
    italics: 'FZYTK.TTF',
    bolditalics: 'FZYTK.TTF',
  }
};
onmessage = function ({ data }) {
  // 工作线程收到主线程的消息
  if(!data) return;
  let pdf = pdfMake.createPdf(data);
  pdf.getBlob((blob) => {
    postMessage(blob)
  }, { progressCallback(num) { postMessage({ type:'progress',num})}});
};

使用中的问题

虽然支持svg,但是svg如果很大它无法配置跨页φ(* ̄0 ̄)

这个问题很重要,因为我用echarts生成的svg图片,无法通过fit属性压缩大小(长宽).所以考虑手动切割图片,但因为对svg的了解不深所以放弃了.后面采用position定位属性手动偏移和计算,在通过pagebreak配置分页.实现跨页效果
下贴手动偏移的代码

interface SvgProps {
  src: string;
  wh: number[]; // [宽,高]
}

const getSvgContents = (svg: SvgProps) => {
  if (!svg) return null;
  let { src, wh } = svg;
  let [width, height] = wh;
  let rw = pageWidth - pageMargins[0] - pageMargins[2];
  let ratio = rw / width;
  let rH = height * ratio;
  let spliteNum = Math.ceil(height / pageHeight); 
  let content = [];
  for (let i = 0; i < spliteNum; i++) {
    content.push({ svg: src, margin: [0, 0, 0, 0], fit: [rw, rH], absolutePosition: { x: 0, y: i && -1 * i * pageHeight }, pageBreak: 'before', preserveLeadingSpaces: true },)
  }
  return content
}

问题解决了,但是这就导致生成pdf的时间变得更长了 o( ̄▽ ̄)o

渲染中会阻塞线程

通过回调本应该拿到进度并绘制在进度条上给用户了解,但是因为它的执行是同步代码,所以会优于页面渲染.同时页面也是阻塞状态,无法操作.这个很难受,想了一下就用webWorker来生成吧.使用中要注意配置<img src="https://webpack.docschina.org/d19378a95ebe6b15d5ddea281138dcf4.svg" width = "20" height = "20" alt="图片名称" align=center />webpack,官方配置链接很简单.我使用的是 chainWebpack,下面就贴一下代码吧.

 chainWebpack(config) {
    config.module.rule()
      .test(/\.worker\.js$/)
      .use('worker-loader')
      .loader('worker-loader')
      .end()
  },

生成时间很长,相对chrome打印而言

我这是页数*1秒,给了一个进度条让用户感觉在工作,尽量减少不适感.

中文乱码(配置个字体)

配置字体就行,不同的字体可以自己生成.我用的一个现成的,地址:https://files.cnblogs.com/files/s313139232/方正姚体vfs_fonts.js

打包教程:http://www.cnblogs.com/xrab/p/7210588.html

打包步骤:

1.在https://github.com/bpampuch/pdfmake下载pdfmake的源文件

2.在根目录用 npm 安装 gulp

npm install gulp --save-dev

3.安装pdfmake依赖包

npm install

4.在cmd运行打包examples/fonts中的.ttf文件的命令。

gulp buildFonts

5.然后在 build 文件中可以找到vfs_fonts.js文件。

由于字体打包文件较大,建议examples/fonts中的.ttf文件只放置一个字体文件。

结语

使用起来非常的人性化,很棒哈.但是最好还是后端借助工具导出,控制更给力,性能更好,前端处理还是有很多不适.

大家有什么问题或者建议可以留言讨论哈 ( •̀ ω •́ )✧

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容