pdfjs生成pdf缩略图

1,666 阅读2分钟

前言

我正在参加「掘金·启航计划」,最近后端老哥找到我讨论新需求,大致是客户在上传 pdf 文件之后,查看时需要显示缩略图,我心想这不是小case嘛😄,so easy!前端上传 pdf 的时候,后端解析一下,生成一张对应的缩略图不就好了嘛(本着能推则推的友好沟通原则),然而后端老哥告诉我由于各种原因,后端改造起来很麻烦,只能靠前端小老弟来解决了,😮‍💨愉快的摸鱼日子一去不返.于是我开始上网查资料,CV战士登场!!!

image.png

最开始我想的是反正项目里预览 pdf 时用到了pdfjs,那在加载缩略图时也直接用pdfjs展示第一页不就好了,这种方案当然是可行的,但是考虑到有点太浪费资源了,为了显示一张缩略图去请求整个pdf资源.所以最后采用的是在用户上传pdf文件时,利用pdfjs生成一张对应的缩略图,和pdf文件一并上传到服务器,完美搞定.(jym有更好的解决方案请务必告诉我)

1.gif

下面就是核心代码,项目采用的是antd的Upload组件,我们只需要拦截原本的上传事件,然后利用pdfjs获取第一页的内容,然后利用canvas转成图片就行啦!

需要注意的是,pdfjs里面需要加载cmap文件,否则你生成的图片可能会是乱码或者空白哦.我这里采用的是这个版本"react-pdf": "5.7.2".

 const onUploadChange = (e: ISafeAny) => {
    const file = e.file;
    if (/pdf/g.test(file.type)) {
      const url = window.URL.createObjectURL(file);
      pdfjs
        .getDocument({ url, cMapUrl: `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/cmaps/`, cMapPacked: true })
        .promise.then((res) => res.getPage(1))
        .then((page) => {
          const scale = 1.5;
          const viewport = page.getViewport({ scale });
          const canvas = document.createElement('canvas');
          const context = canvas.getContext('2d');
          canvas.height = viewport.height;
          canvas.width = viewport.width;
          const renderContext = {
            canvasContext: context!,
            viewport: viewport
          };
          page.render(renderContext).promise.then(() => {
            const src = canvas.toDataURL();// 这里是个base64
            //后续上传操作......
          });
        });
      return;
    }
  };

antd Upload使用方法类似这样

<Upload beforeUpload={() => false} maxCount={1} onChange={onUploadChange} fileList={[]} accept='.png, .jpg, .pdf'>
  上传
</Upload>

image.png

好了,今天的写bug时间就到此为止吧,再写就不礼貌了.