前端React 实现pdf 在线阅读和电⼦合同
前端React实现pdf在线阅读和电⼦合同
⽂章⽬录
介绍
前段时间看到⽹上有个趋势,今后合同也开始变成⽆纸化,如果要签约,只需要在⽹上签名,不需要本⼈去现场。之前没有做过,决定试试看效果。
1. 搭建页⾯
因为是我⾃建的脚⼿架,所以暂时先搭建个⾻架⽤来做测试页⾯的开发。
提供⼀个简单的搭建步骤:1. npx create-react-app [name] --template typescript
[外链图⽚转存失败,源站可能有防盗链机制,建议将图⽚保存下来直接上传(img-zEGRKtws-1644143802262)
(./ReadMe.assets/image-20220206175120080.png)]搭建好页⾯⾻架后,我在前端周报上⾯翻了翻,到
了2个不错的库: js-pdf 和react-pdf
jsPdf : 前端⽣成pdf ⽂件。⽀持直接下载、转成data url 。
react-pdf : 实时展⽰pdf 内容。⽀持打开⽂件和打开链接。注意: 如果使⽤webpack5的话,不要使⽤国内的npm 源,⼀定要⽤国外最新版本的,否则会出现dev-server 崩溃栈溢出的问题。思路如果要实现pdf 版本的合同,我个⼈分为4步:
1. 读取、展⽰合同内容。
2. 制作合同。
3. 制作合同的同时,能实时看到内容。
4. 下载⽂件。
后期扩展:
5. 线上签名。
6. 盖章留戳。
1. 读取、展⽰合同内容利⽤react-pdf 的展⽰和读取功能,实现pdf ⽂件的展⽰。⾸先,先不考虑⽂件的来源,我们以本地的测试pdf
为准。在开发页⾯引⼊react-pdf ,下⾯是实现源码import React, { useState } from 'react';import { Document, Page } from 'react-pdf/dist/esm/entry.webpack';// 引⼊样式,修复不对齐的问题import 'react-pdf/dist/esm/Page/AnnotationLayer.css';import sample from './test.pdf';
1
2
3
4
5
6
7
const PDFDisplay = () => { const [totalPages, setTotalPages] = useState<number>(0) const [pageNumber, setPageNumber] = useState<number>(1) const [file, setFile] = useState(sample) return ( <> <Card style = {{ margin: 8, }}> <Title level={3}> React-pdf 查看/显⽰ pdf 内容 </Title> <div style = {{ margin: 8, }}> <div style = {{ margin: 6, display: 'flex', flexDirection: 'row-reverse', }}> <div className="Example__container__load"> <input onChange={onFileChange} type="file" /> </div> <Button style={{ margin: 4, }} type='primary' onClick={turnHeadPages} >查看⾸页</Button> <Button style={{ margin: 4, }} type='primary' onClick={turnTailPages} >查看尾页</Button> <Button style={{ margin: 4, }} type='primary' onClick={handleReducePages} >上⼀页</Button> <Button style={{ margin: 4, }} type='primary' onClick={handleTurnPages} >下⼀页</Button> </div> <div style={{ display: 'flex', justifyContent: 'center', }}> <Document file={file} onLoadSuccess={(values: any) => setTotalPages(values?.numPages)} options={options} > <Page pageNumber={pageNumber} renderMode='svg' /> </Document> </div>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
可以看到⽂件已经被读取出来:因为react-pdf ⽣成了⼀个隐藏的dom
,所以在复制⽂字的时候,能看到和展⽰的内容⼜区别,甚⾄出现了⼀些位置上的偏移。为了解决这种不对齐的问题,需要引⼊样式,最⼤限度的避免这种样式偏移:因为pdf
是逐页读取的,我并没有采⽤官⽅doc的做法把所有的内容全部展⽰出来,因为需要写上4个按钮,实现灵活操作。这个是按钮的⽅法: </div> </div> <div style={{ margin: 6, display: 'flex', flexDirection: 'row-reverse', }}>第{pageNumber}页, 共{totalPages}页</div> </Card> </> ) }export default PDFDisplay
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86// 引⼊样式,修复不对齐的问题import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
1
2
在展⽰过程中,如果我们的主要内容是汉字,会出现乱码情况。⽽汉字属于utf-8,我们需要额外引⼊⼀些东西,并且对fig 进⾏修改:安装新的plugin :
npm i copy-webpack-plugin -S 打开fig 的配置⽂件,写⼊以下代码: // 翻下页 const handleTurnPages = () => { if (pageNumber < totalPages) setPageNumber(pageNumber + 1) ('已经到最后⼀页!') } // 翻上页 const handleReducePages = () => { if (pageNumber > 1) setPageNumber(pageNumber - 1) ('已经到⾸页!') } // 回到⾸页 const turnHeadPages = () => { if (pageNumber === 1) ('已经是⾸页') else setPageNumber(1) } // 回到尾页 const turnTailPages = () => { if (pageNumber === totalPages) ('已经是尾页') else setPageNumber(totalPages) } // 上传⽂件 const onFileChange = (event: any) => { const file = event?.target.files[0] const isPDF = file?.type === 'application/pdf' if(!isPDF) { (`${file.name}不是⼀个pdf ⽂件!`) return } console.log('event:', event.target.files); setFile(file) }
svg怎么转为pdf1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39// ⾮拉丁语的格式问题修复 // 此处需要修改fig, CopyWebpackPlugin const options = { cMapUrl: 'cmaps/', cMapPacked: true, };
1
2
3
4
5
6
解决了汉字显⽰问题:附录1. jsPDF ⽂档说明⽐较少,需要仔细阅读源码推荐阅读stackoverflow 的常见QA :暂时不⽀持utf-8如果要保存为图⽚,需要使⽤html2canvas 来使⽤,更换为⽀持utf-8的pdfmake 或者pdfkit 实现
1. 下载pdf ⽂件指定内容下载pdf.save()pdf.output()⽤canvas 展⽰效果,并转换下载
2. 显⽰pdf ⽂件本地⽂件展⽰
实时下载结果展⽰const CopyWebpackPlugin = require('copy-webpack-plugin');new CopyWebpackPlugin({ patterns: [ { from: path.join(path.solve('pdfjs-dist/package.json')), 'cmaps'), to: 'cmaps/' }, ],}),
1
2
3
4
5
6
7
8
9
10
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论