前端pdf预览方案

news2024/11/19 17:13:30

前端pdf预览方案

pdf预览一般不需要前端生成pdf文件,pdf文件一般是通过接口,获取pdf文件【responseType:‘blob’,】或二进制文件流【responseType: ‘arraybuffer’,】或者已有的pdf文件。

前端PDF预览通常是通过读取现有的PDF文件,并使用Canvas或SVG等元素在网页上展示PDF内容

前端预览PDF的最好方式还是让服务器端处理,不光对于前端,也包括后端,这应该是最方便的也是最不易出现问题的方法。

通过接口直接获取Canvas文件流,或svg代码或者文件流。避免了前端做pdf读取操作【前端pdf预览插件大多都很老了,各有隐患,而且pdf读取肯定会慢】;同时也避免了可能出现的不同设备出现的兼容性问题【pc,安卓,ios】。

如果一定要前端处理pdf预览,下面方案仅供参考:

![外链图

使用 iframe、embed、新窗口打开【看天吃饭,基本不建议】
<embed src="https://demo/path.pdf">
<iframe src="https://demo/path.pdf"></iframe>

优点:简单,支持大部分 PC 浏览器(IE 不支持)。跨域资源同样可以(无需 cors)
缺点:不支持移动端浏览器,不支持 IE 等低版本浏览器。样式无法自定义。

pdfjs插件【https://www.npmjs.com/package/pdfjs-dist】

pdfjs插件是最流行的、PDF预览、JavaScript库

PDF.js作为Mozilla开发的一个JavaScript库,旨在提供一个纯JavaScript实现的PDF文件解析和渲染解决方案,使用户能在浏览器环境中无缝地查看PDF文档,而无需依赖任何插件。

PDF.js使用现代Web技术,包括WebGL(用于高级图形渲染)和HTML5
Canvas(用于基本绘图操作),来解析PDF文件的内容,并将其转换为可在浏览器中展示的元素。它提供了丰富的API和配置选项,允许开发者根据需求调整界面样式和功能。此外,PDF.js还支持缩放、旋转、拖动等PDF操作,以及导出为图片和提取文字等功能。

缺点:PDF.js是支持iOS预览的,但可能需要注意一些版本兼容性和实现方式的问题。

pdf.js在ios系统里和Safari浏览器可能出现的兼容性问题
  1. Safari版本问题 :某些旧版本的Safari浏览器可能不支持pdf.js所需的一些JavaScript特性或API,导致无法正常使用。例如,早期版本的Safari不支持私有类字段(这是ES2022引入的特性),而某些版本的pdf.js可能使用了这一特性。
  2. 代码实现问题 :如果pdf.js的代码实现与Safari浏览器的某些特性存在冲突,也可能导致无法正常使用。例如,pdf.js在Safari中可能无法正确解析或渲染PDF文件,或者出现空白页面等问题。
二、解决方案
  1. 升级Safari浏览器 :确保你的Safari浏览器是最新版本,以便支持pdf.js所需的JavaScript特性和API。
  2. 使用兼容版本的pdf.js :如果你正在使用的pdf.js版本与Safari存在兼容性问题,可以尝试使用旧版本的pdf.js,这些版本可能更兼容Safari浏览器。例如,有用户报告说将pdf-dist库降级为v2.4.456可以解决在Safari中的兼容性问题。
  3. 调整代码实现 :如果你有能力修改pdf.js的代码,可以尝试调整代码实现以兼容Safari浏览器。例如,避免使用Safari不支持的JavaScript特性或API,或者添加针对Safari的特定处理逻辑。
  4. 使用第三方库或工具 :如果以上方法都无法解决问题,你可以考虑使用其他第三方库或工具来在Safari中预览PDF文件。这些库或工具可能已经针对Safari浏览器进行了优化和测试,具有更好的兼容性和稳定性。
pdfjs的使用方式
// pdf有两种使用方式:
第一种是pdfjs-view(pdfjs-view-es5)分为两个版本/web/viewer-1.html 和 /legacy/web/viewer.html 。legacy 支持低版本浏览器,使用 es5 编写
const res = await downloadPdf({
      date: reportDate.value,
    })
    const resUrl = URL.createObjectURL(res);
    window.open(`./pdf/web/viewer.html?file=${resUrl}`);

第二种是通过js实现:
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>testDemo</title>
  <script src="./pdf/build/pdf.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.7.7/axios.min.js"></script>
  <style>
    .pdf {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100vh;
      background-color: #f4f4f9;
      margin: 0;
      padding: 0;
    }

    #preViewPdf {
      width: 100%;
      height: 100vh;
      background: white;
      box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.2);
      border-radius: 8px;
      overflow-y: auto;
      position: relative;
    }

    #loading {
      position: absolute;
      color: #555;
      font-size: 1.2em;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }

    .pdf-page {
      display: flex;
      justify-content: center;
      margin-bottom: 10px;
    }

    canvas {
      max-width: 100%;
      height: auto;
    }
  </style>
</head>

<body>
  <div class="pdf">
    <div id="preViewPdf">
      <div id="loading">Loading1114...</div>
    </div>
  </div>
</body>
<script>
  window.onload = async function () {
    const el = document.getElementById('preViewPdf');
    const loadingText = document.getElementById("loading");
    const res = await axios({
      url: '/demo.pdf',
      method: "get",
      // responseType: 'arraybuffer',
      responseType: 'blob',
    })
    const resUrl = URL.createObjectURL(res.data);
    // 加载 pdf 资源
    let loadingTask = pdfjsLib.getDocument(resUrl)
    // PDF 加载完成的回调。
    loadingTask.promise.then(function (pdf) {
      pdf.getPage(1).then(function (page) {
        var viewport = page.getViewport({
          scale: 1,
        });
        // var scale = (500 / viewport.width).toFixed(2)
        // console.log('日志:', scale);
        // viewport = page.getViewport({
        //   scale: scale
        // });
        var canvas = document.createElement('canvas');
        el.appendChild(canvas)
        var context = canvas.getContext('2d');
        canvas.height = viewport.height;
        canvas.width = viewport.width;

        // 创建了一个canvas画板用来存放
        var renderContext = {
          canvasContext: context,
          viewport: viewport
        };
        loadingText.style.display = 'none'
        page.render(renderContext);
      });
    }, function (reason) {
      console.error(reason)
    })
  }
</script>

</html>
另一个插件pdfH5【https://www.npmjs.com/package/pdfh5】

注意:

  1. 这是一个很老的插件,可能这个差价的部分依赖插件已经停止维护了;

  2. 如果有报错,请复制example运行,然后对照相关文件,以及package.json,缺什么补什么

  3. 如果有某些字体显示不了,那可能是pdf.js缺少相关字库解析,可以尝试更改cMapUrl,建议去官方地址找版本

  4. 如果IOS下pdf显示不了,安卓却可以,可能是pdf精度过高导致,Safari浏览器canvas渲染绘制图片宽高不能超过16777216,超过会不显示

    如果可以用,这个插件使用还是很方便的,但是如果有问题,还是换回pdf.js吧

示例:
<template>
  <div id="app">
	<div id="demo"></div>
  </div>
</template>
<script>
  import Pdfh5 from "pdfh5";
  export default {
    name: 'App',
	data() {
	  return {
	    pdfh5: null
	  };
	},
	mounted() {
		//实例化
	  this.pdfh5 = new Pdfh5("#demo", {
		pdfurl: "../../static/test.pdf",
		// cMapUrl:"https://unpkg.com/pdfjs-dist@3.8.162/cmaps/",
		// responseType: "blob" // blob arraybuffer
	  });
	  //监听完成事件
	  this.pdfh5.on("complete", function (status, msg, time) {
		console.log("状态:" + status + ",信息:" + msg + ",耗时:" + time + "毫秒,总页数:" + this.totalNum)
		//禁止手势缩放
		this.pdfh5.zoomEnable(false);
	  })
	}
  }
</script>

<style>
	@import "pdfh5/css/pdfh5.css";
	*{
	padding: 0;
	margin: 0;
	}
	html,body,#app {
	width: 100%;
	height: 100%;
	}
</style>
下载 PDF【一个简单的办法,特殊情况可用】
  1. 下载头
  2. 直接打开
    1. 如果浏览器不支持解析 PDF 那么可以触发下载。
    2. 如果浏览器支持解析 PDF,那么会变成预览。
    3. 这个时候我们可以给 a 标签加上 download 来触发下载。(需要同域)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2243512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kotlin return与return@forEachIndexed

Kotlin return与returnforEachIndexed fun main() {val data arrayOf(0, 1, 2, 3, 4)println("a")data.forEachIndexed { index, v ->if (v 2) {//类似while循环中的continue//跳过&#xff0c;继续下一个forEachIndexed迭代returnforEachIndexed}println("…

MATLAB绘制克莱因瓶

MATLAB绘制克莱因瓶 clc;close all;clear all;warning off;% clear all rand(seed, 100); randn(seed, 100); format long g;% Parameters u_range linspace(0, 2*pi, 100); v_range linspace(0, pi, 50); [U, V] meshgrid(u_range, v_range);% Parametric equations for t…

DDRPHY数字IC后端设计实现系列专题之数字后端floorplanpowerplan设计

3.2.3 特殊单元的布局 布图阶段除了布置 I/O 单元和宏单元&#xff0c;在 28nm 制程工艺时&#xff0c;还需要处理两种特 殊的物理单元&#xff0c;Endcap 和 Tapcell。 DDRPHY数字IC后端设计实现系列专题之后端设计导入&#xff0c;IO Ring设计 &#xff08;1&#xff09;拐…

css uniapp背景图宽度固定高度自适应可以重复

page {height: 100%;background-image: url(https://onlinekc.a.hlidc.cn/uploads/20241115/350f94aaf493d05625a7ddbc86c7804e.png);background-repeat: repeat;background-size: contain;} 如果不要重复 把background-repeat: repeat;替换background-repeat: no-repeat;

CC工具箱使用指南:【CAD导出界址点Excel】

一、简介 群友定制工具。 面图层导出界址点Excel表之前已经做过好几个&#xff0c;这个工具则是将CAD导出Excel。 CAD数据如下&#xff1a; 工具将如上截图中的边界线导出界址点Excel&#xff0c;并记录下面内的文字。 二、工具参数介绍 点击【定制工具】组里的【CAD导出界…

输出比较简介

输出比较简介 主要是用来输出PWM波形&#xff0c;这个波形是驱动电机的&#xff08;智能车和机器人等&#xff09;必要条件 OC&#xff08;Output Compare&#xff09;输出比较&#xff0c;还有IC&#xff0c;全称是Input Capture&#xff0c;意为输入捕获&#xff0c;还有CC…

力扣(leetcode)题目总结——辅助栈篇

leetcode 经典题分类 链表数组字符串哈希表二分法双指针滑动窗口递归/回溯动态规划二叉树辅助栈 本系列专栏&#xff1a;点击进入 leetcode题目分类 关注走一波 前言&#xff1a;本系列文章初衷是为了按类别整理出力扣&#xff08;leetcode&#xff09;最经典题目&#xff0c…

unity老猿随笔

下面是我最近开始整理的一些unity的基础知识和疑难杂症&#xff0c;如果大家有什么可以分享出来的经验&#xff0c;可以评论区留言&#xff0c;验证后整理进来&#xff0c;全猿学习&#xff01;如果有不对的地方&#xff0c;也欢迎指正&#xff0c;避免误人子弟&#xff01; l…

『VUE』30. 生命周期的介绍(详细图文注释)

目录 生命周期生命周期的8阶段生命周期小例子总结 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 生命周期 每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤&#xff0c;比如设置好数据侦听&#xff0c;编译模板&#xf…

Go语言跨平台桌面应用开发新纪元:LCL、CEF与Webview全解析

开篇寄语 在Go语言的广阔生态中&#xff0c;桌面应用开发一直是一个备受关注的领域。今天&#xff0c;我将为大家介绍三款基于Go语言的跨平台桌面应用开发框架——LCL、CEF与Webview&#xff0c;它们分别拥有独特的魅力和广泛的应用场景。通过这三款框架&#xff0c;你将能够轻…

华为HCCDA云技术认证--网络服务

大家好呀&#xff01;我是reload。今天继续带大家学习华为HCCDA云技术认证&#xff0c;涵盖华为云最为核心的计算、存储、网络、数据库、安全、部署等服务。今天学习网络服务相关内容。 登录华为云官网&#xff1a;https://www.huaweicloud.com/ &#xff0c;进入首页&#xff…

rocketmq5源码系列--(一)--搭建调试环境

说在前头&#xff1a;阿里的rocketmq的文档是真他妈的烂的1b&#xff0c;很多东西都不说&#xff0c;全靠自己看源码&#xff0c;摸索&#xff0c;草&#xff0c;真的要吐血了 rocketmq的版本5而不是版本4&#xff0c;版本5比版本4多了个proxy rocketmq5 三个组件&#xff1a;…

如何通过电脑监控软件远程监控一台电脑的所有屏幕画面记录

7-1 本教程介绍一个简单的工具&#xff0c;可以安装在电脑中&#xff0c;按设置的时间间隔&#xff0c;自动对屏幕截图保存&#xff0c;并且可以在有网络的其它电脑上远程提取截图文件。 该软件用于自动记录电脑的屏幕画面内容和变化&#xff0c;如果你有这方面的使用场景&am…

Redis 概 述 和 安 装

安 装 r e d i s: 1. 下 载 r e dis h t t p s : / / d o w n l o a d . r e d i s . i o / r e l e a s e s / 2. 将 redis 安装包拷贝到 /opt/ 目录 3. 解压 tar -zvxf redis-6.2.1.tar.gz 4. 安装gcc yum install gcc 5. 进入目录 cd redis-6.2.1 6. 编译 make …

Spring Boot汽车资讯:科技与汽车的新篇章

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了汽车资讯网站的开发全过程。通过分析汽车资讯网站管理的不足&#xff0c;创建了一个计算机管理汽车资讯网站的方案。文章介绍了汽车资讯网站的系统分析部分&…

CSS:高级寄巧

精灵图 为什么需要精灵图呢&#xff1f; 一个网页中往往会应用很多小背景图作为修饰&#xff0c;当网页中的图像过多时&#xff0c;服务器就会频繁地接收和发送 请求图片&#xff0c;造成服务器请求压力过大&#xff0c;这将大大降低页面的加载速度。 因此&#xff0c;为了有…

【原创】如何备份和还原Ubuntu系统,非常详细!!

前言 我在虚拟机装了一个xfce4的Ubuntu桌面版&#xff0c;外加输入法、IDEA等&#xff0c;我想将这个虚拟机里的系统直接搬到物理机中&#xff0c;那我可以省的再重新装一遍、配置xfce4桌面、修改一堆快捷键还有配置idea了&#xff0c;那直接说干就干。 本教程基于Ubuntu24.0…

SAM_Med2D 训练完成后boxes_prompt没有生成mask的问题

之前对着这这篇文章去微调SAM_Med2D(windows环境),发现boxes_prompt空空如也。查找了好长时间问题SAM-Med2D 大模型学习笔记&#xff08;续&#xff09;&#xff1a;训练自己数据集_sam训练自己数据集-CSDN博客 今天在看label2image_test.json文件的时候发现了一些端倪: 官方…

数据结构-二叉搜索树(Java语言)

目录 1.概念 2.查找search 3.插入insert ​编辑4.删除remove&#xff08;难点&#xff09; 5.性能分析 1.概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树 : 1.若它的左子树不为空&#xff0c;则左子树上所有节点的值都…

【蓝桥杯备赛】深秋的苹果

# 4.1.1. 题目解析 要求某个区间内的数字两两相乘的总和想到前缀和&#xff0c;但是这题重点在于两两相乘先硬算&#xff0c;找找规律&#xff1a; 比如要算这串数字的两两相乘的积之和&#xff1a; 1, 2, 3 1*2 1*3 2*3 1*(23) 2*3 前缀和数组&#xff1a; 1 3 6 发现…