前端-将PDF文件每页拆分为一张图片(如100页PDF文件拆为100张图片平铺展示、上传)

390 阅读2分钟

一.需求描述

用户上传pdf文件后,需要将pdf逐页平铺展示给用户进行评论。

二.需求分析

需求服务端也能实现,但耗时较长。

三.核心方案

使用pdfjs-dist包,该插件是解决前端预览pdf文件的方案(像翻书一样,前后翻页展示),但我们只需要基于它提供的能力进行改造即可实现我们的需求。

四.详细示例

import * as pdfjsLib from 'pdfjs-dist';
import workerSrc from 'pdfjs-dist/build/pdf.worker.entry';
pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;

const fileReader = new FileReader();
fileReader.onload = function() {
  const uint8 = new Uint8Array(this.result);
  const loadingTask = pdfjsLib.getDocument(uint8); 
  loadPDFFile(loadingTask);
};
fileReader.readAsArrayBuffer(file); // file是拿到的上传的pdf文件

async function loadPDFFile(loadingTask) {
    const pdf = await loadingTask.promise; // 拿到pdf对象
    const pagesNum = pdf.numPages; // 拿到页数
    // 循环获取每一页
    for (const i = 0; i < pagesNum; i++) {
        const page = await pdf.getPage(i);
        const viewport = page.getViewport(1);
        // 创建canvas渲染当前页
        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        canvas.height = viewport.height;
        canvas.width = viewport.width;
        const renderContext = {
          canvasContext: context,
          viewport,
        };
        const renderTask = page.render(renderContext);
        // 截止到这里,就实现了在canvas上渲染某一页(至于翻页,可以结合相关api,但这不是我们今天的需求)。
        
        // 但我们的需求是拿到每一页平铺展示或者全部上传,见以下代码
        renderTask.promise.then(async function() {
          // 假如需要平铺展示,我们把canvas转为base64
          const base64 = canvas.toDataURL('image/jpeg');
          setImgs([...imgs, base64]); // react
          
          // 上传,需要转blob格式(uploadBlob方法要求)
          canvas.toBlob(async blob => {
              const ext = blob?.type.split('/')[1] || 'png';
              uploadBlob(blob, `${i}.${ext}`) // uploadBlob是上传方法,可自己封装ajax
          })
        })
    }
  }

五.性能优化

如果pdf页数比较多,需要考虑for循环中使用canvas渲染的浏览器性能消耗;以及上传存储云请求的并发控制。

请求的最大并行数量控制可参考我的另外一篇《# 前端ajax请求并发数量控制》juejin.cn/post/729341…

六.注意事项

1.因该包的最新版本使用较高的es版本编写(如#关键字),在我的项目中直接引用新版本会导致编译错误

该demo使用版本为"pdfjs-dist": "^2.0.943"