前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >解决Android的WebView无法打开PDF的方案

解决Android的WebView无法打开PDF的方案

原创
作者头像
一冷
发布2023-07-12 00:56:40
3K0
发布2023-07-12 00:56:40
举报
文章被收录于专栏:前端汇总前端汇总

背景

最近自家产品开发使用中收到反馈,安卓内嵌网页无法打开PDF,而IOS可以打开。其实安卓无法打开分以下几种情况:

  • 有.pdf后缀但是文档比较小的——可以打开
  • 有.pdf后缀但是文档比较大的——无法打开
  • 无.pdf后缀的——都打不开

原因分析

Android的内置WebView引擎 主要用于显示网页内容和基本的文本渲染 ,对于复杂的多媒体和特定文件类型的渲染支持有限, 不直接支持打开大型的带有.pdf后缀的PDF文件预览对于不具有.pdf后缀的PDF文件,WebView默认将其视为普通的文本或二进制文件,因此无法直接预览

IOS的WebView使用的是 WebKit引擎 ,该引擎内置了对PDF文件的支持, 可以直接预览和展示PDF内容 。所以IOS的WebView可以打开带有.pdf后缀的文件,并提供内置的PDF查看器,使用户可以直接再应用中查看PDF文件。 对于没有.pdf后缀的文件,IOS仍可以预览并打开,因为IOS系统的预览功能会自动识别文件类型,并使用适当的预览器打开文件

这里我主要针对无.pdf后缀的,H5利用Canvas和PDF.js,给一下我开发时的解决方法。不过我也会将我收集到的安卓的方案写这里,不过我不是安卓开发工程师,欢迎补充。

解决方案

安卓方案

  1. 使用特定的PDF库:Android上有许多为PDF预览和操作提供支持的 第三方库 ,如Adobe PDF Library和MuPDF等。这些库可以在WebView中渲染和打开PDF文件。
  2. 使用其他应用程序:(通过使用Inteynt机制?),可以调用系统中预装的PDF阅读器应用程序或其他支持PDF的应用程序来打开和预览PDF文件。可以根据文件类型和URI来指定打开PDF文件的应用程序。例如,使用封装pdf的应用程序,如Adobe Acrobat Reader或其他PDF阅读器应用程序

H5使用pdf.js利用Canvas将页面渲染出来

  1. 引入PDF.js(注意如果要下载下来使用的化, pdf.worker.min.js 也要下载下来) <script src="https://unpkg.com/pdfjs-dist@1.9.426/build/pdf.min.js"></script>
  2. 主要JS代码
代码语言:html
复制
 <script>
    // 获取页面参数
    // 测试:?pdf=https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf
    let url = new URLSearchParams(window.location.search).get("pdf");
    let pdfDoc = null;

    function createPage() {
      let div = document.createElement("canvas");
      document.body.appendChild(div);
      return div;
    }

    function renderPage(num) {
      pdfDoc.getPage(num).then(function (page) {
        let viewport = page.getViewport(2.0);
        let canvas = createPage();
        let ctx = canvas.getContext('2d');

        canvas.height = viewport.height;
        canvas.width = viewport.width;

        page.render({
          canvasContext: ctx,
          viewport: viewport
        });
      });
    }

    // 如果是由后端的pdf链接地址,且跨域需要携带cookie验证,getDocument中传{ url: url, withCredentials: true }
    PDFJS.getDocument({ url: url }).then(function (pdf) {
      pdfDoc = pdf;

      for (let i = 1; i <= pdfDoc.numPages; i++) {
        renderPage(i)
      }
    })
  </script>

附整个页面的代码

代码语言:html
复制
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport"
    content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=4.0, user-scalable=no">
  <title>安卓PDF阅读页面</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    canvas {
      width: 100%;
      height: 100%;
      border: 1px solid rgb(221, 221, 221);
    }

    /* 加载中的转圈圈样式 */
    .spinner-box {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      z-index: 2;
      background-color: rgba(0, 0, 0, 0.3);
    }

    .spinner-box img {
      width: 9.3333vw;
      height: 9.3333vw;
    }

    .spinner-box .title {
      margin: 2.6667vw 0 0;
      font-size: 3.2vw;
      color: #fff;
      text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.5);
      white-space: pre-line;
      text-align: center;
    }

    .spinner-box .spinner {
      width: 9.3333vw;
      height: 9.3333vw;
      animation: rotator 1.4s linear infinite;
    }

    @keyframes rotator {
      0% {
        transform: rotate(0deg);
      }

      100% {
        transform: rotate(270deg);
      }
    }

    .spinner-box .path {
      stroke-dasharray: 187;
      stroke-dashoffset: 0;
      transform-origin: center;
      animation: dash 1.4s ease-in-out infinite, colors 5.6s ease-in-out infinite;
    }

    @keyframes colors {
      0% {
        stroke: #fff;
      }

      25% {
        stroke: #f7e7d7;
      }

      50% {
        stroke: #eecfaf;
      }

      75% {
        stroke: #e5b788;
      }

      100% {
        stroke: #dd9f60;
      }
    }

    @keyframes dash {
      0% {
        stroke-dashoffset: 187;
      }

      50% {
        stroke-dashoffset: 46.75;
        transform: rotate(135deg);
      }

      100% {
        stroke-dashoffset: 187;
        transform: rotate(450deg);
      }
    }
  </style>

</head>
<script src="https://unpkg.com/pdfjs-dist@1.9.426/build/pdf.min.js"></script>
<body>
  <div id="loading" class="spinner-box">
    <!-- 上传中 -->
    <svg class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg">
      <circle class="path" fill="none" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle>
    </svg>
  </div>

  <script>
    // 获取页面参数
    // 测试:?pdf=https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf
    let url = new URLSearchParams(window.location.search).get("pdf");
    let pdfDoc = null;

    function createPage() {
      let div = document.createElement("canvas");
      document.body.appendChild(div);
      return div;
    }

    function renderPage(num) {
      pdfDoc.getPage(num).then(function (page) {
        let viewport = page.getViewport(2.0);
        let canvas = createPage();
        let ctx = canvas.getContext('2d');

        canvas.height = viewport.height;
        canvas.width = viewport.width;

        page.render({
          canvasContext: ctx,
          viewport: viewport
        });
      });
    }

    let loading = document.getElementById("loading")

    // 显示加载中
    loading.style.display = "flex";

    // 如果是由后端的pdf链接地址,且跨域需要携带cookie验证,getDocument中传{ url: url, withCredentials: true }
    PDFJS.getDocument({ url: url }).then(function (pdf) {
      pdfDoc = pdf;

      for (let i = 1; i <= pdfDoc.numPages; i++) {
        renderPage(i)
      }
      // 隐藏加载中
      loading.style.display = "none";
    })
  </script>
</body>
</html>

如有不足,欢迎指正

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 原因分析
  • 解决方案
    • 安卓方案
      • H5使用pdf.js利用Canvas将页面渲染出来
      • 附整个页面的代码
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档