vue3移动端实现pdf预览

第一种方式:使用vue-pdf-embed和vue3-pdfjs

使用的插件有:

复制代码
npm i vue-pdf-embed
npm i vue3-pdfjs

html部分:

html 复制代码
	  <div ref="preRef" v-loading="loading" class="pdf-preview">
        <div v-if="pdfState.source" class="pdf-wrap">
          <VuePdfEmbed
            v-for="item in pdfState.numPages"
            :key="item"
            :source="pdfState.source"
            :style="pdfState.scale"
            class="vue-pdf-embed"
            :page="item"
          />
        </div>
        <van-empty v-if="loadError" image="error" description="PDF加载出错了..." />
      </div>

js部分:

html 复制代码
// 引入两个插件相关的
import VuePdfEmbed from 'vue-pdf-embed';
import { createLoadingTask } from 'vue3-pdfjs';
// 以上涉及的参数
const pdfState = reactive({
  source: '', // 预览pdf文件地址
  pageNum: 1, // 当前页面
  scale: 1, // 缩放比例
  numPages: 0, // 总页数
  width: '400px', // 宽度
});
const preRef = ref();
const detail = ref({});//返回的数据
const loading = ref(true);
const loadError = ref(false);

//  方法
//  接口返回的数据
function getDetail() {
  baseInfoGet({ id: route.currentRoute.value.query.id }).then((res) => {
    detail.value = res.data;
    const url = safeJSONParse(res.data.fileUrl)?.[0].url || '';
    pdfState.source = url;
    console.log('预览地址:', url);
    if (!url) return;
    setTimeout(() => {
      pdfState.width = getComputedStyle(preRef.value)?.width;
      console.log(pdfState.width);
      loadingPdf(url);
    }, 0.5 * 1000);
  });
}
// 加载pdf的方法
function loadingPdf(url) {
  const loadingTask = createLoadingTask(url);
  loadingTask.promise.then((pdf) => {
    pdfState.numPages = pdf.numPages;
    loading.value = false;
  }).catch(() => {
    loading.value = false;
    loadError.value = true;
  });
}

我一开始使用的时第一种方法,然后测试之后发现苹果手机会显示pdf加载出错了 ,安卓手机可以正常显示,于是换成了第二种方法。

第二种方式使用pdfjs-dist,苹果手机加载失败需使用版本2.2.228

html 复制代码
npm i pdfjs-dist

html部分:

html 复制代码
      <div class="pdf-viewer">
        <template v-for="item in pageNum" :key="item">
          <canvas :id="`pdf-canvas-${item}`" class="pdf-page" />
        </template>
        <van-empty
          v-if="loadError"
          image="error"
          description="PDF加载出错了..."
        />
      </div>

js部分:

html 复制代码
// 引入插件相关的参数
import * as pdfjs from 'pdfjs-dist';
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;

// html部分涉及的参数
const loadError = ref(false);
const detail = ref({});
let pdfDoc = null; // 一定不能使用响应式的数据,会报错Cannot read from private field---pdf.js
const pageNum = ref(0);
// 处理接口返回的pdf的url
function getDetail() {
  baseInfoGet({ id: route.currentRoute.value.query.id }).then((res) => {
    detail.value = res.data;
    const url = safeJSONParse(res.data.fileUrl)?.[0].url || '';
    showLoadingToast({
      message: '加载中...',
      forbidClick: true,
    });
    console.log('预览地址:', url);
    if (!url) return;
    loadingPdf(url);
  });
}
//加载pdf
function loadingPdf(url) {
  const loadingTask = pdfjs.getDocument(url);
  loadingTask.promise
    .then((pdf) => {
      pdfDoc = pdf;
      pageNum.value = pdf.numPages;
      nextTick(() => {
        renderPage();
      });
    })
    .catch(() => {
      closeToast();
      loadError.value = true;
    });
}
// 渲染pdf
function renderPage(num = 1) {
  pdfDoc.getPage(num).then((page) => {
    const canvas = document.getElementById(`pdf-canvas-${num}`);
    const ctx = canvas.getContext('2d');
    const scale = 1.5;
    const viewport = page.getViewport({ scale });
    // 画布大小,默认值是width:300px,height:150px
    canvas.height = viewport.height;
    canvas.width = viewport.width;
    // 画布的dom大小, 设置移动端,宽度设置铺满整个屏幕
    const { clientWidth } = document.body;
    // 减去2rem使用因为我的页面左右加了padding
    canvas.style.width = `calc(${clientWidth}px - 2rem)`;
    // 根据pdf每页的宽高比例设置canvas的高度
    canvas.style.height = `${
      clientWidth * (viewport.height / viewport.width)
    }px`;
    canvas.height = viewport.height;
    canvas.width = viewport.width;
    page.render({
      canvasContext: ctx,
      viewport,
    });
    if (num < pageNum.value) {
      renderPage(num + 1);
    } else {
      closeToast();
    }
  });
}

用了第二种插件后,苹果手机还是加载不出来,后面查到因为pdfjs-dist有时候会出现部分手机比如iphone6和iphone8渲染不出pdf问题

解决办法:
将pdfjs-dist版本改为2.2.228

html 复制代码
npm i  pdfjs-dist@2.2.228

然后就加载出来了,最后在各个环境测试的时候又发现,微信小程序里面打开这个模块,pdf还是没加载出来,console之后发现请求401,报错信息是登陆访问超时,发现pdfjs加载pdf时没有携带token

遂,在加载url时添加token即可

pdfjs加载pdf时携带token

html 复制代码
//加载pdf
function loadingPdf(url) {
 const afterUrl = {
    url,
    httpHeaders: {
      token: `Bearer-${localStorage.getItem('token')}`,
    },
  };
  const loadingTask = pdfjs.getDocument(afterUrl );
  loadingTask.promise
    .then((pdf) => {
      pdfDoc = pdf;
      pageNum.value = pdf.numPages;
      nextTick(() => {
        renderPage();
      });
    })
    .catch(() => {
      closeToast();
      loadError.value = true;
    });
}

添加之后就加载出来了

相关推荐
夏日白云1 小时前
《PDF解析工程实录》第 8 章|融合策略:不是兜底,而是信息利用率最大化
pdf·llm·大语言模型·rag·文档解析
m5655bj2 小时前
通过 Python 提取 PDF 表格数据
服务器·python·pdf
PascalMing2 小时前
Pascal.Edge物联网平台:生产企业设备数据采集与管理解决方案
物联网·c#·vue·数据采集
清平乐的技术专栏3 小时前
电脑自带Edge浏览器进行PDF文件合并
前端·edge·pdf
Irene19913 小时前
文档加密加水印只读分享:WPS/PPT编辑后导出PDF(附:百度网盘分享流程)
pdf·加密·wps·pptx·只读
启扶农4 小时前
lecen:一个更好的开源可视化系统搭建项目--介绍、搭建、访问与基本配置--全低代码|所见即所得|利用可视化设计器构建你的应用系统-做一个懂你的人
低代码·vue·node·所见即所得·表单设计·页面可视化·页面设计器
2501_930707784 小时前
使用C#代码重新排列 PDF 页面
开发语言·pdf·c#
爱分享的小诺4 小时前
在谷歌浏览器上的谷歌商店进不去,可以使用...
vue·谷歌浏览器·扩展插件
南风微微吹4 小时前
【2026年3月】计算机二级WPS真题试卷及解析14套~电子版PDF
pdf·wps·计算机二级wps
夏日白云6 小时前
《PDF解析工程实录》第 9 章|端到端多模态模型:不是接不住,而是要看业务能接受什么
pdf·llm·大语言模型·多模态·rag·文档解析