React中实现PDF的在线预览功能
最近项目中遇到了PDF预览的需求,客户要求可以在线查看PDF文件内容,不想下载下来再打开,踩了一些坑,做一个总结。
最简单的实现方式
目前几乎市面上的浏览器都原生支持了PDF预览功能,也就是说把一个在线的pdf地址,直接放在浏览器里是可以直接打开的。所以实现思路很简单粗暴,直接内嵌一个iframe
就可以实现预览。
基本所有的功能都齐全了,如果不是极致要求兼容和一致性,都使用这个方案。
PDF.js
这是mozilla
开源的一个前端pdf渲染框架,目前市面上常见的PDF渲染库基本都是基于它做的封装。
我没有采用这种方案是因为它默认是单独启动一个html,然后把pdf地址传进去,我个人不太喜欢。
React-pdf
react-pdf
是基于pdf.js
的封装,可以使用React的语法去灵活自定义。
安装
npm install react-pdf
// or
yarn add react-pdf
配置
详细配置方案参考官网:wojtekmaj/react-pdf: Display PDFs in your React app as easily as if they were images.
说一下我的配置方法,我没有使用本地的配置,使用的是CDN,一方面项目本身已经比较大了,还有一方面是后面可能要对webpack
升级,就先不折腾。
PS:如果你的部署环境完全是内网运行的,不要用我这种方法。
需要配置2个内容,一个是worker,一个是cmap(这个不配置好像也能用),如下:
// 配置worker
pdfjs.GlobalWorkerOptions.workerSrc = `//cdn.staticfile.org/pdf.js/${pdfjs.version}/pdf.worker.min.js`;
cmap的配置在Document
组件里设置,我使用也还是CDN。
<Document options={{
cMapUrl: `https://unpkg.com/browse/pdfjs-dist@${pdfjs.version}/cmaps/`,
cMapPacked: true,
}} file={url} onLoadSuccess={onDocumentLoadSuccess}>
{Array.from(
new Array(numPages),
(el, index) => (
<Page
renderTextLayer={false}
width={740}
key={`page_${index + 1}`}
pageNumber={index + 1}
/>
)
)}
</Document>
上面的代码实现的是把所有的PDF页面渲染出来,效果如图:
遇到的问题
在渲染知网论文的时候会有一些中文无法显示的情况出现,搜索了一下似乎是bug,参考这里:Chinese type 1 font does not render: Warning: Unknown type 1 charstring command of “0” · Issue #5790 · mozilla/pdf.js,解决方案参考这里:Error during font loading: Unable to load binary CMap at: ../web/cmaps/GBK-EUC-H.bcmap · Issue #10660 · mozilla/pdf.js