vue3——实现pdf文件预览,解决‘no-cors‘ to fetch the resource with CORS 跨域问题,pdfjs-dist案例源码

😉 你好呀,我是爱编程的Sherry,很高兴在这里遇见你!我是一名拥有十多年开发经验的前端工程师。这一路走来,面对困难时也曾感到迷茫,凭借不懈的努力和坚持,重新找到了前进的方向。我的人生格言是——认准方向,坚持不懈,你终将迎来辉煌!欢迎关注我😁,我将在这里分享工作中积累的经验和心得,希望我的分享能够给你带来帮助。

功能描述

点击文件名称,预览pdf文件,要求只能预览,不能做其他操作。

实现效果展示

在这里插入图片描述

项目环境介绍

node v18+
pdfjs-dist v2.16.105
vue3
nuxt3
typescript

实现步骤

安装pdfjs-dist
npm i pdfjs-dist@2.16.105
封装独立pdf组件

<template>
  <Modal v-model="visible" width="1300" footer-hide @on-cancel="cancel">
    <div id="pdf-view" class="page-center">
      <canvas v-for="page in state.pdfPages" :key="page" id="pdfCanvas" />
      <div id="text-view"></div>
    </div>
  </Modal>
</template>
<script>
import "pdfjs-dist/web/pdf_viewer.css";
import * as PDF from "pdfjs-dist";
PDF.GlobalWorkerOptions.workerSrc = "/pdf.worker.js";
const pdf = "/科学第一单元 声音 知识点.pdf";
let pdfDoc = null;
export default {
  data() {
    return {
      state: {
        // 文件路径
        pdfPath: pdf,
        // 总页数
        pdfPages: 1,
        // 页面缩放
        pdfScale: 2,
      },
      visible: false,
    };
  },
  mounted() {
    // this.loadFile(this.state.pdfPath)
  },
  methods: {
    init(url) {
      this.visible = true;
      this.state.pdfPath = url
      console.log('pdf url', url)
      this.$nextTick(() => {
        this.loadFile(this.state.pdfPath);
      })
      // this.loadFile(this.state.pdfPath);
    },
    cancel() {
      this.visible = false;
    },
    loadFile(url) {
      PDF.getDocument({
        url,
        cMapUrl: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.16.105/cmaps/",
        cMapPacked: true,
      }).promise.then((pdf) => {
        pdfDoc = pdf;
        // 获取pdf文件总页数
        this.state.pdfPages = pdf.numPages;
        this.$nextTick(() => {
          this.renderPage(1); // 从第一页开始渲染
        });
      });
    },
    renderPage(num) {
      pdfDoc.getPage(num).then((page) => {
        const canvas = document.getElementById("pdfCanvas");
        const ctx = canvas.getContext("2d");
        const viewport = page.getViewport({ scale: this.state.pdfScale });
        canvas.width = viewport.width;
        canvas.height = viewport.height;
        const renderContext = {
          canvasContext: ctx,
          viewport,
        };
        page.render(renderContext);
      });
    },
  },
};
</script>

在父组件中使用
<script lang="ts" setup>
import PdfFrame from '@/components/PdfFrame';
const pdfFrameRef = ref<InstanceType<typeof PdfFrame> | null>(null);
const viewFile = (url:string) => {
  const path = '/file' + url
  pdfFrameRef.value?.init(path)
}
</script>
<template>
  <div>
    <a @click="viewFile(info.attachPath)">{{ info.attachName }}</a>
  </div>
  <PdfFrame ref="pdfFrameRef" />
</template>

注意:info.attachPath 是pdf文件的地址;info.attachName是文件名称。文件的地址需要换成自己的,如果文件打不开要先检查文件的地址是否正确。

常见问题
No “GlobalWorkerOptions.workerSrc” specified.

起初没有配置GlobalWorkerOptions.workerSrc,报了下面的错误

在这里插入图片描述
在这里插入图片描述
需要将pdfjs-dist包中的build文件夹下的pdf.worker.js文件复制到public文件夹下
在这里插入图片描述
在这里插入图片描述
然后添加下面这行代码

PDF.GlobalWorkerOptions.workerSrc = "/pdf.worker.js";
跨域问题

Access to fetch at “url” from origin “url” present on the request, If an opaque responseserves your needs, set the request s mode to ‘no-cors’ to fetch the resource with CORS disabled.
在这里插入图片描述
解决跨域问题需要使用代理,我的项目配置如下

nitro: {
    devProxy: {
      '/file': {
        target: 'https://yours.cn/file', // 这里是接口地址
        changeOrigin: true,
        prependPath: true,
      },
    },
}
   
文件地址不正确引发的报错

假如文件地址不正确会报下面这种错误,请先检查文件路径是否能够正常访问。
在这里插入图片描述

总结

以上就是如何使用pdfjs-dist实现文件预览功能,按照上面的步骤如果有其他问题,欢迎在评论区给我留言哦!

### Vue3PDF 文件预览实现方法 在 Vue3实现 PDF 文件流的预览功能可以通过多种方式完成。以下是基于提供的引用内容以及专业知识的一种解决方案。 #### 使用 `vue-pdf` 和自定义逻辑处理文件流 通过结合 `vue-pdf` 插件和后端返回的 PDF 流数据,可以轻松实现前端展示 PDF 的需求。具体代码如下: ```javascript // 定义请求函数用于获取 PDF 文件流 export function fetchPdfStream() { return request({ url: &#39;/api/getPdf&#39;, // 假设这是获取 PDF 数据的接口地址 method: &#39;get&#39;, responseType: &#39;blob&#39; // 设置响应类型为 blob }); } ``` 在组件中加载并渲染 PDF 文件流: ```html <template> <div id="pdf-container"> <!-- vue-pdf 提供的 PdfComponent --> <pdf v-for="i in numPages" :key="i" :src="pdfSrc"></pdf> </div> </template> <script> import pdf from &#39;vue-pdf&#39;; // 导入 vue-pdf 组件 export default { components: { pdf }, data() { return { pdfSrc: null, numPages: undefined }; }, methods: { async loadPdf() { const response = await fetchPdfStream(); // 调用上面定义的方法获取 PDF 流 this.pdfSrc = URL.createObjectURL(new Blob([response.data])); // 将 Blob 对象转换成可访问链接 // 加载 PDF 并计算总页数 const loadingTask = pdf.createLoadingTask(this.pdfSrc); const pdfData = await loadingTask.promise; this.numPages = pdfData.numPages; // 获取 PDF 总页数 } }, mounted() { this.loadPdf(); } }; </script> ``` 上述代码实现了从服务器拉取 PDF 文件流,并将其作为资源嵌入到页面中的过程[^1]。同时利用了 `vue-pdf` 来解析和显示 PDF 页面的内容[^2]。 --- #### 可选方案:使用 `PDF.js` 手动控制 PDF 渲染 如果希望更灵活地操作 PDF 显示,则可以直接引入官方库 `PDF.js` 进行开发。这种方式允许开发者完全掌控 PDF 解析流程,适合复杂场景下的定制化需求。 安装依赖: ```bash npm install pdfjs-dist --save ``` 编写核心逻辑: ```javascript import { getDocument } from &#39;pdfjs-dist&#39;; export default { data() { return { pages: [] }; }, methods: { async renderPdfFromStream() { try { const response = await fetch(&#39;/api/getPdf&#39;); // 请求 PDF 文件流 const arrayBuffer = await response.arrayBuffer(); const loadingTask = getDocument(arrayBuffer); // 创建 PDF 文档对象 const pdfDoc = await loadingTask.promise; for (let i = 1; i <= pdfDoc.numPages; i++) { const page = await pdfDoc.getPage(i); const viewport = page.getViewport({ scale: 1.5 }); // 计算视口尺寸 const canvas = document.createElement(&#39;canvas&#39;); const context = canvas.getContext(&#39;2d&#39;); canvas.width = viewport.width; canvas.height = viewport.height; await page.render({ canvasContext: context, viewport }).promise; this.pages.push(canvas.toDataURL()); // 存储每一页的数据 URI } console.log(&#39;All Pages Rendered:&#39;, this.pages.length); } catch (error) { console.error(&#39;Error rendering PDF:&#39;, error.message); } } }, mounted() { this.renderPdfFromStream(); } }; ``` 此部分展示了如何手动解析 PDF 文件流并通过 Canvas API 动态绘制每一帧图像[^3]。 --- #### 注意事项 - **问题**:当涉及远程服务时,请确认 CORS 是否已正确配置。 - **性能优化**:对于大体积 PDF 或多页文档建议采用按需加载策略减少内存占用。 - **浏览器兼容性测试**:确保目标环境支持所使用的 JavaScript 特性和第三方插件版本。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sherry Tian

打赏1元鼓励作者

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值