前端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怎么转为pdf
1
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小时内删除。