前端使用pdfjs预览pdf文件,文字展示乱码,如何使用系统默认字体展示?

我使用pdfjs预览pdf文件,但是有的pdf中使用的字体是不常见的字体,预览时会导致字体乱码,如图:
image.png

我希望遇到不支持的字体时使用默认字体展示,
或者可以加载新增ttf字体文件支持字体(我尝试配置cMapUrl和standardFontDataUrl 但是没有效果)。

请问应该如何让文字正常展示

import * as PDFJS from 'pdfjs-dist'

const isdevelopment =  import.meta.env.MODE === 'development'
PDFJS.GlobalWorkerOptions.workerSrc = `${isdevelopment ? 'http://localhost:20008' : '/ts_ai'}/assets/js/pdfWorker5.5.207/pdf.worker.min.js`




 _loadFile(url) {
      //初始化pdf
      let loadingTask = PDFJS.getDocument({
        url: url,
        cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@5.5.207/cmaps/',
        cMapPacked: true,
        standardFontDataUrl: `${isdevelopment ? 'http://localhost:200008' : '/ts_ai'}/assets/js/pdfjs/standard_fonts/`
      })
      loadingTask.promise.then((pdf) => {
        this.pdfDoc = pdf
        this.pdf_pages = this.pdfDoc.numPages
        this.$nextTick(() => {
          this._renderPage(1)
        })
      })
    },
    _renderPage(num) {
      // console.log('_renderPage-num', num)
      //渲染pdf页
      const that = this
      this.pdfDoc.getPage(num).then((page) => {
        let canvas = document.getElementById('the_canvas' + num)
        let ctx = canvas.getContext('2d')
        let dpr = window.devicePixelRatio || 1
        let bsr =
          ctx.webkitBackingStorePixelRatio ||
          ctx.mozBackingStorePixelRatio ||
          ctx.msBackingStorePixelRatio ||
          ctx.oBackingStorePixelRatio ||
          ctx.backingStorePixelRatio ||
          1
        let ratio = dpr / bsr
        let viewport = page.getViewport({ scale: this.pdf_scale })
        canvas.width = viewport.width * ratio
        canvas.height = viewport.height * ratio
        canvas.style.width = viewport.width + 'px'
        if (!that.pdf_div_width) {
          if (Number(that.pdf_div_width.replace(/px/g, '')) > viewport.width) {
            that.pdf_div_width = viewport.width + 'px'
          }
        }
        
        canvas.style.height = viewport.height + 'px'
        ctx.setTransform(ratio, 0, 0, ratio, 0, 0)
        let renderContext = {
          canvasContext: ctx,
          viewport: viewport,
          intent: 'print',
        }
        page.render(renderContext)
        if (this.pdf_pages > num) {
          this._renderPage(num + 1)
        }
      })
    },
阅读 567
2 个回答

pdf 转图片 展示图片

PDF.js 字体乱码通常是因为缺少标准 PDF 字体(如宋体、楷体等中文字体)的 fallback 机制。
方法一:禁用字体渲染(走 Canvas 路径,最简单)
在 PDF.js viewer 初始化时设置:

const loadingTask = pdfjsLib.getDocument({
  url: 'your.pdf',
  disableFontFace: true,  // 关键:禁用 @font-face,用 canvas 渲染
  cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@4.0.379/cmaps/',
  cMapPacked: true,
  standardFontDataUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@4.0.379/standard_fonts/',
});

disableFontFace: true 强制走 Canvas 路径,不依赖浏览器字体,大多数乱码问题能解决。
方法二:补充中文字体 fallback CSS

@font-face {
  font-family: 'SimSun';
  src: local('SimSun'), local('宋体'), local('Songti SC');
  unicode-range: U+4E00-9FFF; /* CJK 范围 */
}

@font-face {
  font-family: 'SimHei';
  src: local('SimHei'), local('黑体'), local('Heiti SC');
  unicode-range: U+4E00-9FFF;
}

.textLayer span {
  font-family: 'SimSun', 'SimHei', 'Microsoft YaHei', 'PingFang SC', sans-serif !important;
}

方法三:加载自定义 TTF

const CMAP_URL = '/cmaps/';
const CMAP_PACKED = true;
const STANDARD_FONT_DATA_URL = '/standard_fonts/';

// 自定义字体映射
pdfjsLib.GlobalWorkerOptions.standardFontDataUrl = STANDARD_FONT_DATA_URL;

const loadingTask = pdfjsLib.getDocument({
  url: 'your.pdf',
  cMapUrl: CMAP_URL,
  cMapPacked: CMAP_PACKED,
  standardFontDataUrl: STANDARD_FONT_DATA_URL,
  // 字体替换映射
  fontExtraProperties: true,
  useSystemFonts: false,
});

方法四:服务端预处理(根治)
如果以上都不行,服务端用 pdftocairoghostscript 把 PDF 字体嵌入化:

# 将所有字体转为内置(子集化)
gs -o output.pdf -sDEVICE=pdfwrite \
  -dEmbedAllFonts=true \
  -dSubsetFonts=true \
  input.pdf

推荐顺序:先试方法一 disableFontFace: true,大多数场景直接解决。如果是 PDF.js 查看器(viewer.html),在 viewer.js 里搜 disableFontFace 改就行。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题