Решение для решения проблемы, связанной с тем, что Android WebView не может открыть PDF-файл.
Решение для решения проблемы, связанной с тем, что Android WebView не может открыть PDF-файл.

фон

Недавно во время разработки и использования наших собственных продуктов мы получили отзывы о том, что веб-страницы, встроенные в Android, не могут открывать PDF-файлы, но IOS может его открывать. На самом деле, есть несколько ситуаций, когда Android невозможно открыть:

  • Существует суффикс .pdf, но документ относительно небольшой — его можно открыть.
  • Существует суффикс .pdf, но документ относительно большой — его невозможно открыть.
  • Без суффикса .pdf — невозможно открыть.

Анализ причин

Встроенный движок Android WebView. В основном используется для отображения веб-контента и базового рендеринга текста. ограниченная поддержка рендеринга сложных мультимедиа и файлов определенных типов, Открытие предварительного просмотра больших PDF-файлов с суффиксом .pdf напрямую не поддерживается.PDF-файлы без суффикса .pdf WebView по умолчанию обрабатывает их как обычные текстовые или двоичные файлы, поэтому их нельзя просмотреть напрямую.

WebView для IOS использует WebKit-движок , в движке есть встроенная поддержка PDF-файлов, Может напрямую просматривать и отображать содержимое PDF. . Таким образом, WebView на IOS может открывать файлы с суффиксом .pdf и предоставляет встроенную программу просмотра PDF-файлов, позволяющую пользователям просматривать PDF-файлы непосредственно в приложении. Для файлов без суффикса .pdf IOS все равно может просматривать и открывать их, поскольку функция предварительного просмотра системы IOS автоматически определяет тип файла и использует соответствующую программу предварительного просмотра для открытия файла.

Здесь я в основном сосредотачиваюсь на H5 без суффикса .pdf, используя Canvas и PDF.js, и даю решение во время разработки. Однако я также напишу здесь собранные мной решения для Android. Однако я не являюсь инженером-разработчиком Android, поэтому любые дополнения приветствуются.

решение

Android-решение

  1. Используйте специальную библиотеку PDF: многие из них на Android обеспечивают поддержку предварительного просмотра и обработки PDF-файлов. Сторонние библиотеки ,Как Adobe PDF Библиотека и MuPDF и т. д. Эти библиотеки могут отображать и открывать PDF-файлы в WebView.
  2. С помощью других приложений: (с помощью механизма Интейнт?),Вы можете вызвать предустановленное приложение для чтения PDF-файлов в системе или другие приложения, поддерживающие PDF, чтобы открыть и просмотреть PDF-файлы. Приложения, открывающие файлы PDF, можно указать на основе типа файла и URI. Например,Использование приложения, которое упаковывает 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>

Если есть какие-то недостатки, пожалуйста, поправьте меня.

boy illustration
Углубленный анализ переполнения памяти CUDA: OutOfMemoryError: CUDA не хватает памяти. Попыталась выделить 3,21 Ги Б (GPU 0; всего 8,00 Ги Б).
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Прочитайте нейросетевую модель Трансформера в одной статье
boy illustration
.ART Теплые зимние предложения уже открыты
boy illustration
Сравнительная таблица описания кодов ошибок Amap
boy illustration
Уведомление о последних правилах Points Mall в декабре 2022 года.
boy illustration
Даже новички могут быстро приступить к работе с легким сервером приложений.
boy illustration
Взгляд на RSAC 2024|Защита конфиденциальности в эпоху больших моделей
boy illustration
Вы используете ИИ каждый день и до сих пор не знаете, как ИИ дает обратную связь? Одна статья для понимания реализации в коде Python общих функций потерь генеративных моделей + анализ принципов расчета.
boy illustration
Используйте (внутренний) почтовый ящик для образовательных учреждений, чтобы использовать Microsoft Family Bucket (1T дискового пространства на одном диске и версию Office 365 для образовательных учреждений)
boy illustration
Руководство по началу работы с оперативным проектом (7) Практическое сочетание оперативного письма — оперативного письма на основе интеллектуальной системы вопросов и ответов службы поддержки клиентов
boy illustration
[docker] Версия сервера «Чтение 3» — создайте свою собственную программу чтения веб-текста
boy illustration
Обзор Cloud-init и этапы создания в рамках PVE
boy illustration
Корпоративные пользователи используют пакет регистрационных ресурсов для регистрации ICP для веб-сайта и активации оплаты WeChat H5 (с кодом платежного узла версии API V3)
boy illustration
Подробное объяснение таких показателей производительности с высоким уровнем параллелизма, как QPS, TPS, RT и пропускная способность.
boy illustration
Удачи в конкурсе Python Essay Challenge, станьте первым, кто испытает новую функцию сообщества [Запускать блоки кода онлайн] и выиграйте множество изысканных подарков!
boy illustration
[Техническая посадка травы] Кровавая рвота и отделка позволяют вам необычным образом ощипывать гусиные перья! Не распространяйте информацию! ! !
boy illustration
[Официальное ограниченное по времени мероприятие] Сейчас ноябрь, напишите и получите приз
boy illustration
Прочтите это в одной статье: Учебник для няни по созданию сервера Huanshou Parlu на базе CVM-сервера.
boy illustration
Cloud Native | Что такое CRD (настраиваемые определения ресурсов) в K8s?
boy illustration
Как использовать Cloudflare CDN для настройки узла (CF самостоятельно выбирает IP) Гонконг, Китай/Азия узел/сводка и рекомендации внутреннего высокоскоростного IP-сегмента
boy illustration
Дополнительные правила вознаграждения амбассадоров акции в марте 2023 г.
boy illustration
Можно ли открыть частный сервер Phantom Beast Palu одним щелчком мыши? Супер простой урок для начинающих! (Прилагается метод обновления сервера)
boy illustration
[Играйте с Phantom Beast Palu] Обновите игровой сервер Phantom Beast Pallu одним щелчком мыши
boy illustration
Maotouhu делится: последний доступный внутри страны адрес склада исходного образа Docker 2024 года (обновлено 1 декабря)
boy illustration
Кодирование Base64 в MultipartFile
boy illustration
5 точек расширения SpringBoot, супер практично!
boy illustration
Глубокое понимание сопоставления индексов Elasticsearch.
boy illustration
15 рекомендуемых платформ разработки с нулевым кодом корпоративного уровня. Всегда найдется та, которая вам понравится.
boy illustration
Аннотация EasyExcel позволяет экспортировать с сохранением двух десятичных знаков.