Skip to content

配置统一免登录页面

日期:2023.11.10

场景 实现pdf预览功能

描述

INFO

后端将pdf文件放在了oss上,前端拿到pdf的链接,并且在前端进行展示

思路

  1. 采用iframe直接展示pdf文件

需要注意几点:

1. `iframe`必须要求文件时本地或者不能跨域,必须不能跨域
2. 用`iframe`展示,里面的内容时不受你控制的

意思就是:后端给你的文件长什么样子,前端就只能展示,没法对他进行较好的调整

当然也可以采用一些transfrom:scale(x)这种来调整大小,但是说到底其实都是调整的iframe

  1. 采用embed展示pdf文件

这个其实和iframe没什么区别,因为iframe内部其实也是使用embed来进行展示的

这边我也就不多说了

  1. 使用pdfJs处理

注意:

1. `npm i pdf-dist`文件,下载了,但是没用

会提示报错:没有安装这个库,但其实已经安装了,很诡异

并且npm安装显示,增加了0个依赖,很诡异

2. 采用`CDN`来进行引用,不采用`npm`进行安装

但是在创建pdfJs实例的时候,需要使用window["pdfjs-dist/build/pdf"]

因为PDF-dist的打包方式采用的UMD这种,所以当我们使用<script>标签引入库时,库的内容就会自动被添加到window对象上。

pdfjs-dist文件的模块名是pdf,但是pdfjavascript的关键字,不可以直接使用window.pdf,为了避免这个问题,使用数组索引的方式来访问pdfjs-dist

代码

typescript
/**
 * @description: 使用pdfJS实现将pdf转换成图片
 * @param {string} url: pdf的url
 * @returns string: 返回图片的base64
 */

export function changePdfToImg(url: string, imgRef: React.RefObject<HTMLImageElement>) {
  console.log("url", url);
  const pdfjsLib = window["pdfjs-dist/build/pdf"];
  const canvas = document.createElement("canvas");
  pdfjsLib.getDocument(url).promise?.then((pdf: any) => {
    console.log("pdf", pdf);
    return pdf.getPage(1);
  }).then((page: any) => {
    const viewport = page.getViewport({ scale: 1 });
    const canvasContext = canvas.getContext("2d");
    canvas.height = viewport.height;
    canvas.width = viewport.width;
    const renderContext = {
      canvasContext,
      viewport,
    };
    return page.render(renderContext).promise;
  }).then(() => {
    const img = canvas.toDataURL("image/png");
    // console.log("img", img);
    imgRef.current!.src = img;
    return img;
  });
}

代码解读

  1. Promise的链式调用
    1. pdfjsLib.getDocument(url)

使用getDocumnet()来加载pdf文件

返回的是一个Promise对象

2. `.promise`,访问`promise`属性
3. `.then()`:`pormise`执行成功的回调

也就是这个时候,pdf文件已经加载好了,下面只需要对文件进行绘制

page形参:成功获取的PDF页面对象

  1. renderContext:作用就是将pdf文件渲染到canvas
  2. 下面就是将canvas转化成图片的Data URL
  3. 然后将url设置搭配图片上即可

参考链接

pdfjs-dist 在vite4.x 下的使用问题 - 掘金

GPT3.5问答