react h5 PDF转图片

背景

        最近在做一个h5嵌入安卓app的项目,里面有个pdf预览的功能,后端直接返回的pdf链接。一开始我图省事就直接用iframe嵌入了,在pc电脑上显示是没什么问题的,但是在app上打开的时候发现显示不了。最开始我是去找了原生的开发,问了他这个问题,是不是原生可以改一下,毕竟pc可以显示,是不是做下兼容就好了。后面原生给我的答复是:和webview的内核有关,webview的内核 和浏览器的内核不一样

        没办法啦,只能自己想办法,应该把pdf转成图片就可以显示了,冲!

解决过程

        说干就干,直接面向百度编程,网上还是很多这种案例的,下面是解决的过程:

        1.引入pdfjs
npm install pdfjs-dist --save
        2.创建canvas
<canvas ref={canvasRef} width={200} height={100} />
        3. 将PDF转为图片显示在canvas上
import { getDocument } from "pdfjs-dist/legacy/build/pdf.mjs";
import { useEffect, useRef } from "react";
import "pdfjs-dist/build/pdf.worker.mjs";


const canvasRef = useRef(null);
  useEffect(() => {
    if (props.visible) {
      const loadingTask = getDocument({
        url: props.pdfUrl,
        cMapUrl: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.5.207/cmaps/", // 解决字体不全问题
        cMapPacked: true,
      });
      loadingTask.promise
        .then(async (pdf) => {
          const canvas: any = canvasRef.current;
          const context: any = canvas.getContext("2d", {
            willReadFrequently: true,
          });
          // 循环遍历每一页pdf,将其转成图片
          for (let i = 1; i <= pdf._pdfInfo.numPages; i++) {
            // 获取pdf页
            const page = await pdf.getPage(i);
            // 获取页的尺寸
            const viewport = page.getViewport({ scale: 1 });
            // 设置canvas的尺寸
            canvas.width = viewport.width;
            canvas.height = viewport.height;
            // 将pdf页渲染到canvas上
            await page.render({
              canvasContext: context,
              viewport: viewport,
            }).promise;
            // 将canvas转成图片,并添加到页面上
            const img = new Image();
            img.src = canvas.toDataURL("image/png");
            img.onload = () => {
              // 计算图片在画布中的位置和大小,这里简单让图片居中显示
              const x = (canvas.width - img.width) / 2;
              const y = (canvas.height - img.height) / 2;
              // 将图片绘制到 canvas 上
              context.drawImage(img, x, y);
            };
          }
        })
        .then(
          function () {
            console.log("# End of Document");
          },
          function (err) {
            console.error("Error: " + err);
          }
        );
    }
  }, [props.visible]);

        到这里就完成啦!可以看一下效果图片

        

遇到的问题     

        在开发的时候也是遇到了一些奇奇怪怪的问题,下面是一些解决方案:

        1.因为我是做的h5,所以需要考虑一下显示的美观问题。刚开始图片显示的时候是根据pdf大小去直接展示的,很大一张,很丑。最开始我是常事缩小pdf的大小:page.getViewport({ scale: 0.5}),把scale改成0.5,但是这样实践下来,发现图片被压缩了,很模糊,看不清楚。后面直接用的比较暴力的办法去解决的哈哈哈哈哈哈。

        直接更改了canvas的宽高,因为项目里做了px转rem的操作,所以可以实现图片自适应屏幕啦。大佬们有更好的解决办法嘛?

        2.遇到过字体不全的报错

        最开始是想让后端同学去改一下pdf的字体的,但是不知道咋回事,他改了没生效,没办法,只能继续自己找解决办法了😂。最后解决的办法很简单,就是加了两行代码:

const loadingTask = getDocument({
        url: props.pdfUrl,
        cMapUrl: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.5.207/cmaps/", // 解决字体不全问题
        cMapPacked: true,
      });

以上就是全部过程啦!完结!撒花!🎉


使用了两天,发现cMapUrl的cdn资源链接不是很稳定,会出现字体不现实的问题。后来换成了https://unpkg.com/pdfjs-dist@2.6.347/cmaps/ 这个链接,目前还没发现问题,观察一段时间再说。

                                                                                                                          编辑于2025-3-17

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值