pdf预览很强大的插件是pdf.js,这是原生js实现的插件,能兼容大部分浏览器,对于它的使用方法,在传统的web项目中就是viewer.html?file="文件名称",但是对于react项目来说,pdf.js的文件要放在静态文件夹下,文件较大,也尝试使用npm install pdfjs-dist安装,但是按照官方的例子传文件的base64编码时显示不出来,下载官方的代码在浏览器查看它的例子也显示不成功,不知道什么原因,花了好多时间也没解决,最后还是使用react-pdf,gitHub地址:https://github.com/wojtekmaj/react-pdf
查看react-pdf安装包发现react-pdf也是引用了pdf.js,使用react-pdf的写法传文件的base64编码可以正常显示出来。
自己调一下样式,分页使用ant-design的分页组件,显示效果如下:
后台返回的pdf文件数据:
后台返回的是文件流二进制数据,预览是新开的窗口,关键代码
stream.blob().then(blob => {//stream 后台返回的数据
const r = new FileReader(); // 读取file对象,提取图片base64编码,用于预览
r.readAsDataURL(blob);
r.onload = e => {
const eurl = e.target.result;
const myWindow = window.open('/preview', '_blank');// 新开窗口跳转到preview.js
myWindow.onload = () => myWindow.postMessage(eurl, window.origin)// 页面加载完传pdfbase64编码参数过去
};
});
预览页面的代码:preview.js
import React, { Component, Fragment } from 'react';
import { Document, Page } from 'react-pdf';
import { Pagination } from 'antd'
import styles from './Preview.less'
class Preview extends Component{
state={
pdfBase64:null,
numPages:0,
pageNumber:1
}
componentDidMount(){
window.addEventListener('message', (event) => {
this.setState({pdfBase64:event.data})
}, false)
}
onDocumentLoad = ({ numPages }) => {
this.setState({ numPages });
}
onChangePage=(page)=>{
this.setState({ pageNumber:page });
}
render(){
const {pdfBase64,numPages,pageNumber} = this.state
return(
<Fragment>
<Document
className={styles.preview}
onLoadSuccess={this.onDocumentLoad}
file={pdfBase64}
renderMode='svg'
>
<Page className={styles.page} pageNumber={pageNumber} scale={1.5} />
</Document>
<Pagination
className={styles.pagination}
total={numPages}
showTotal={total => `共 ${total} 页`}
current={pageNumber}
pageSize={1}
size='small'
onChange={this.onChangePage}
/>
</Fragment>
)
}
}
export default Preview
出现一些问题。。。。
有些文档字体出现很怪异的现象:
后来发现把用svg渲染改成canvas就可以了。
<Document
className={styles.preview}
onLoadSuccess={this.onDocumentLoad}
file={pdfBase64}
renderMode='canvas'
>
<Page className={styles.page} pageNumber={pageNumber} scale={scale} />
</Document>