在项目中有这样一个需求,需要调用其他系统业务API生成页面(canvas)渲染图表,并将图表导出成PDF文件,上传到服务器,并将文件地址,传给第三方业务系统,使第三方业务系统能够通过文件服务器下载该图表PDF文件
以上就是原始的需求描述了
当我们接到这个需求的时候就已经大概或许猜测出,这事流程较复杂,能不能直接甩锅到后端同学,让后端同学去完成这一系列的骚操作。
尽管 前后端 都是可以完成的。
但是后端有一个难点(耗时点)是画图表的操作;只要图表能够画出来,剩下的无非就是 canvas 转 pdf 文件,然后调用文件服务 service 进行上传,同步第三方系统,完事。
呐. 需要前端提供 画图表的模版什么的,或者需要前端吧canvas 转 图片 或者 pdf .
这一波操作下来, 好像前端的工作量也没怎么减少。
经过一系列沟通与讨论,发现一个很nice点就是,生成图表的业务,已经封装成npm 包了。
那这事 就显得 不那么棘手了。
现在 我们具体简单整理 整个流程:
step1. 在本系统安装 图表 npm 包,调用业务系统API 生成图表
step2. 将生成的canvas图表 转成 pdf
step3. 将pdf上传拿到文件路径
step4. 将pdf文件路径同步给第三方
整个需求梳理下来的流程就大概就是这了。
经过上述的需求分析 我们大致 明确了每一步需要做的操作了。
现在我们就具体分析一下可能存在的细节或遗漏点
先查看了 图表的npm 包,先集成 这个包 进入 我们自己的业务系统,并隐藏
同时生成多张图表,并将多张生成一个PDF文件 ???
PDF的分页问题?
PDF的临时存储 ? 要不要先下载下来 让用户再手动选择文件进行上传?能不能接受这多一步的操作,或者我们能不能规避这一步的操作呢?
PDF的上传? 到底是用户手动选择上传 还是 程序自动静默上传 ?其实我们都偏向后者,减少用户操作,一步到位
因为是多张图表,具体多少张不知道,可能几张,可能几时上百张,没有给出具体阈值?
这个问题就显得比较尖锐了,主要反应在两个方面:
第一方面:一次渲染这么多canvas 页面必定会卡顿或直接浏览器崩溃
第二方面:就算上面说的页面不卡顿或者浏览器不崩溃,生成的pdf文件大小如果太大,上传也将是一个问题,这个时候就又要考虑大文件上传方案了。
第三方面:这一系列的操作虽然是自动静默进行的,能不能在页面上反馈出进度或状态,让用户知晓当前进行到哪一步了。
那我们还是本着先实现功能,再优化细节的方式进行了demo的编写;
本文就仅给出大概实现思路和部分参考代码:
集成 图表 组件 comA
<
button
@
click
=
"handleCanvasToPdf"
>
下载PDF
</
button
>
<
div
ref
=
"canvasList"
>
<
com-a
v-for
=
"(item,index) in list"
:key
=
"item.id"
:ref
=
"'comA_'+index"
/>
安装
jsPDF
npm install jspdf -S
methods
:{
async
handleLoadData
(
){
const
res =
await
API
.
request
(
'/xxx/xxx'
,{
size
:
3
})
const
list = res.
data
|| [],
handleCanvasToPdf
(
){
const
canvasList =
this
.
$refs
.
canvasList
.
querySelectorAll
(
'canvas'
)
if
(!canvasList.
length
){
return
}
const
cacheImageList = canvasList.
map
(
(
canvas
)=>
{
return
canvas.
toDataURL
(
'image/jpeg'
,
1
)
const
pdf =
new
jsPDF
(
'p'
,
'pt'
,
'a4'
)
const
width = pdf.
internal
.
pageSize
.
getWidth
()
const
height = pdf.
internam
.
pageSize
.
getHeight
()
cacheImageList.
forEach
(
(
img,index
)=>
{
pdf.
addImage
(img,
'JPEG'
,
0
,
0
,width,height)
if
(imageCacheList.
length
-
1
!== index){
padf.
addPage
()
pdf.
save
(
'temp.pdf'
)
运行上面的方法 就能自动下载pdf 文件了
打开下载下来的
PDF
文件,果然如预期,直呼内行 .......
当调整参数 size = 20 后等请求完成后,立马点击
下载PDF
新的问题就来了:
PDF中 部分 页面内容空白,而且是靠后,越往后越空白!甚至在前几页内容都不完整,有些图表内容也仅仅只渲染了一半;
只需搭眼一看,就知道是渲染时间的问题,所有的canvas 还没有渲染完成就被拿去转换成文件了。要如何解决这个问题呢 ? 请看下一篇!
最后的最后
经过我们简单的demo 发现整个过程还是很顺畅的 现在所暴露的问题也慢慢浮现了,让我们简单整理下一现在要解决的问题:
如何不下载PDF到本地磁盘,就能上传???
如何保证PDF多页面不空白,也就是如何保证canvas列表已经全部渲染???
如何保证很多个图表渲染的时候页面不卡顿???
下一篇 我们继续分析如何解决上述问题
使用jsPdf 将页面生成PDF文件并自动上传 DEMO(二)
下面有请今天的主角小趴菜: