React 中使用 pdf.js 将 pdf 转换成图片

pdf.js 主要用于在网页上展示 pdf 文档,是一个用户解析和渲染 pdf 文件的开源库。本文主要介绍如何在 react 中使用 pdf.js 解析 pdf 文件,并最终转换成图片形式。

一、 安装 pdf.js 库文件

要在 react 中使用 pdf.js,首先需要安装对应的依赖。对此 pdf.js 提供了 pdfjs-dist 库,我们可以通过 npm 进行下载.

npm install pdfjs-dist --save

二、 在组件中使用。

在 pdf.js 的 issues 中找到 pdf.js 在 react 中的使用方法,参考 issue:Using pdf.js in React】 

1. 引入 pdf.js 文件

2. 编写文件上传组件

3. 编写上传属性和方法

4. pdf 解析

5. canvas 设置

6. 生成图片

从上面的代码可以看出,由 pdf 生成图片主要需要经历以下几个过程:

上传 pdf 文件 -> 解析 pdf -> 生成 canvas 对象 -> 转换成图片 -> (插入页面或导出文件)

三、在项目中查看效果

导入后查看

完整的 jsx 代码如下:

  1 import React from 'react';
  2 import { Modal } from 'antd'
  3 import * as PDFJS from "pdfjs-dist";
  4 import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';
  5 
  6 const Dragger = Upload.Dragger;
  7 
  8 PDFJS.GlobalWorkerOptions.workerSrc = pdfjsWorker;
  9 
 10 export default class ImportPdf extends React.Component {
 11     state = {
 12         pdf: '',
 13     }
 14 
 15     openPage(pdfFile, pageNumber, context) {
 16         var scale = 2;
 17         pdfFile.getPage(pageNumber).then(function (page) {
 18             // reference canvas via context
 19             const viewport = page.getViewport(scale);
 20             var canvas = context.canvas;
 21             canvas.width = viewport.width;
 22             canvas.height = viewport.height;
 23             canvas.style.width = "100%";
 24             canvas.style.height = "100%";
 25             var renderContext = {
 26                 canvasContext: context,
 27                 viewport: viewport
 28             };
 29             page.render(renderContext);
 30         });
 31         return;
 32     }
 33 
 34     exportImg(self) {
 35         // 将 canvas 导出成 img
 36         $('#pdf-container canvas').each(function (index, ele) {
 37             var canvas = document.getElementById("pageNum" + (index + 1));
 38             // 将 canvas 转成 base64 格式的图片
 39             let base64ImgSrc = canvas.toDataURL("image/png")
 40             const img = document.createElement("img")
 41             img.setAttribute('class', 'pdf-img');
 42             img.src = base64ImgSrc
 43             img.style.width = '100%';
 44             // 将图片挂载到 dom 中
 45             $('#pdf-container').append(img);
 46         });
 47     }
 48 
 49     readPdf(file) { 
 50         // pdf.js无法直接打开本地文件,所以利用FileReader转换
 51         const reader = new FileReader();
 52         reader.readAsArrayBuffer(file);
 53         reader.onload = function (e) {
 54             const typedarray = new Uint8Array(this.result);
 55             const loadingTask = PDFJS.getDocument(typedarray);
 56             loadingTask.promise.then(function (pdf) {
 57                 if (pdf) {
 58                     // pdf 总页数
 59                     const pageNum = pdf.numPages;
 60                     for (let i = 1; i <= pageNum; i++) {
 61                         // 生成每页 pdf 的 canvas
 62                         const canvas = document.createElement('canvas');
 63                         canvas.id = "pageNum" + i;
 64                         // 将 canvas 添加到 dom 中
 65                         $('#pdf-container').append(canvas);
 66                         const context = canvas.getContext('2d');
 67                         self.openPage(pdf, i, context);
 68                     }
 69                     setTimeout(() => {
 70                         self.exportImg(self)
 71                     }, 1000);
 72                 }
 73             }).catch(function (reason) {
 74                 console.error("Error: " + reason);
 75             });
 76         };
 77     }
 78 
 79     render() {
 80         const self = this;
 81         const uploadProps = {
 82             name: 'file',
 83             accept: '.pdf',
 84             action: '',
 85             onChange(info) {
 86                 const status = info.file.status;
 87                 if (status != 'done') {
 88                     self.setState({ loading: true });
 89                 }
 90                 if (status !== 'uploading') {
 91                     console.log(info.file, info.fileList);
 92                 }
 93                 if (status === 'done') {
 94                     self.setState({ loading: false });
 95                     message.success(`${info.file.name} 导入成功`);
 96                     // 解析 pdf 文件
 97                     self.readPdf(info.file.originFileObj);
 98                 } else if (status === 'error') {
 99                     console.log(`${info.file.name} 导入失败`);
100                 }
101             },
102         };
103         return (
104             <Modal
105                 title="导入pdf"
106                 width={480}
107                 className="import-pdf-modal"
108                 footer={null}
109             >
110                 <Spin tip="导入中" spinning={this.state.loading}>
111                     <Dragger {...uploadProps} id="document">
112                         <p className="ant-upload-drag-icon">
113                             <Icon type="inbox" />
114                         </p>
115                         <p className="ant-upload-text">点击或将文件拖拽到这里上传</p>
116                         <p className="ant-upload-hint">支持扩展名:.pdf</p>
117                         <div id='pdf-container' style={{ height: 0, overflow: 'hidden' }}></div>
118                     </Dragger>
119                 </Spin>
120             </Modal>
121         )
122     }
123 }

【参考】

pdf.js

Is there a pre-built version PDF.js available?

pdf2img

原文地址:https://www.cnblogs.com/wx1993/p/12533899.html