更新记录

0.2.5(2026-06-04)

  • 修复:普通 uni-app App 包装层接入 Android/iOS UTS 原生 PDF 组件,避免 App 端只渲染空白普通 view
  • 兼容:普通 uni-app App 传入 http/https PDF 时自动先下载到临时文件,再交给原生组件渲染
  • 兼容:H5 默认 h5Mode="auto",PDF.js 加载失败、跨域失败或超时后自动降级到浏览器原生 iframe
  • 兼容:H5 viewer 同步放入 static/pdf-viewer,避免构建后 components/pdf-viewer/web-viewer.html 未作为静态资源服务导致路由回退空白
  • 优化:H5 viewer 改为多 CDN 动态加载 PDF.js,并通过 viewerId 回传真实 load/error/pageChange 状态
  • 修复:H5 本地相对路径不再错误拼接为 file://,改为按当前页面 URL 解析

0.2.4(2026-05-19)

  • 修复:兼容 HBuilderX 5.07 / uni-app x 5.07 云打包,移除 Android 端旧版 UniNativeViewElementgetAndroidActivitybindAndroidView 原生 View 绑定路径,避免 compileReleaseKotlin 出现 unresolved reference
  • 调整:Android 原生 PDF 组件统一通过 utssdk/app-android/index.vueNVLoadNVLoadedNVLayoutedNVBeforeUnload 生命周期挂载和释放 PdfNativeView
  • 文档:补充用户反馈的 Android UTS 插件编译失败说明,提示更新插件目录后重新提交云打包

0.2.3(2026-05-07)

  • 调整:iOS 端暂时取消上一页、下一页原生翻页栏,仅保留 PDF 基础渲染能力,优先保证 iOS 加载稳定性
  • 保留:Android 端继续保留分页模式下的原生上一页、下一页按钮和页码显示
  • 修复:iOS 端回退到最小 PDFView 渲染路径,移除翻页按钮、页码栏和 target-action 相关实现,降低下载加载 PDF 后闪退风险
  • 优化:iOS PDF 加载继续使用本地文件 URL、主线程渲染和渲染任务序号控制,避免重复触发渲染
  • 修复:补回 components/view-pdf/view-pdf.uvue 标准组件入口,改用 <native-view> 绑定原生实现,避免同名组件递归
  • 文档:明确当前版本分页能力以 Android 为主,iOS 后续稳定后再恢复翻页能力
查看更多

平台兼容性

uni-app(5.0)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- 5.0 12 -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

uni-app x(5.0)

Chrome Safari Android iOS 鸿蒙 微信小程序
5.0 12 - -

其他

多语言 暗黑模式 宽屏模式
× ×

view-pdf(uni-app + uni-app x)

view-pdf 是一个支持 uni-appuni-app x 的 PDF 查看器插件,支持多平台展示 PDF 文档。

功能特性

  • 支持 paged 分页查看
  • 支持 scroll 全文滚动查看
  • 支持 quality 清晰度调节
  • 支持 zoom 缩放倍率调节
  • 支持页面跳转、获取当前页和总页数
  • 支持页面切换事件
  • 多平台兼容:H5、App(Android/iOS)

平台支持

平台 支持情况 说明
H5 ✅ 支持 使用 PDF.js
App-Android ✅ 支持 使用 PdfRenderer 原生组件
App-iOS ✅ 支持 使用 PDFKit 原生组件
小程序 ❌ 暂不支持 需使用 webview

安装

将插件目录放入项目:

  • uni_modules/view-pdf

uni-app 使用示例

H5 平台

<template>
  <view class="page">
    <view-pdf 
      class="viewer" 
      :url="pdfUrl" 
      :quality="3" 
      :zoom="1.4" 
      mode="scroll"
      @load="onLoad"
      @error="onError"
      @pageChange="onPageChange"
      ref="pdfViewer"
    />
  </view>
</template>

<script setup>
import { ref } from 'vue'

const pdfViewer = ref(null)
const pdfUrl = ref('https://example.com/sample.pdf')
const statusText = ref('等待加载')
const pageText = ref('')

const onLoad = (e) => {
  statusText.value = 'PDF 加载成功'
}

const onError = (e) => {
  statusText.value = e.errMsg || 'PDF 加载失败'
}

const onPageChange = (e) => {
  pageText.value = `${e.currentPage}/${e.totalPages}`
}

const goToPage = (pageIndex) => {
  pdfViewer.value.goToPage(pageIndex)
}

const getCurrentPage = () => {
  pdfViewer.value.getCurrentPageIndex().then(index => {
    pageText.value = `当前页:${index}`
  })
}

const getTotalPages = () => {
  pdfViewer.value.getTotalPages().then(total => {
    pageText.value = `总页数:${total}`
  })
}
</script>

<style>
.page {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.viewer {
  flex: 1;
}
</style>

App 平台(本地文件)

<template>
  <view class="page">
    <view-pdf 
      class="viewer" 
      :url="pdfPath" 
      :quality="2" 
      :zoom="1" 
      mode="paged"
      @load="onLoad"
      @error="onError"
      @pageChange="onPageChange"
      ref="pdfViewer"
    />
  </view>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const pdfViewer = ref(null)
const pdfPath = ref('')
const statusText = ref('等待加载')
const pageText = ref('')

onMounted(() => {
  downloadPdf()
})

const downloadPdf = () => {
  uni.downloadFile({
    url: 'https://example.com/sample.pdf',
    success: (res) => {
      if (res.statusCode === 200 && res.tempFilePath) {
        pdfPath.value = res.tempFilePath
      }
    },
    fail: (err) => {
      statusText.value = err.errMsg || '下载失败'
    }
  })
}

const onLoad = (e) => {
  statusText.value = 'PDF 加载成功'
}

const onError = (e) => {
  statusText.value = e.errMsg || 'PDF 加载失败'
}

const onPageChange = (e) => {
  pageText.value = `${e.currentPage}/${e.totalPages}`
}

const goToPage = (pageIndex) => {
  pdfViewer.value.goToPage(pageIndex)
}

const getCurrentPage = () => {
  const index = pdfViewer.value.getCurrentPageIndex()
  pageText.value = `当前页:${index}`
}

const getTotalPages = () => {
  const total = pdfViewer.value.getTotalPages()
  pageText.value = `总页数:${total}`
}
</script>

<style>
.page {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.viewer {
  flex: 1;
}
</style>

uni-app x 使用示例

<template>
  <view class="page">
    <view-pdf class="viewer" :url="pdfPath" :quality="3" :zoom="1.4" mode="scroll" />
  </view>
</template>

<script setup lang="uts">
import { ref } from 'vue'

const pdfPath = ref('')

uni.downloadFile({
  url: 'https://mirrors.tuna.tsinghua.edu.cn/CTAN/info/lshort/chinese/lshort-zh-cn.pdf',
  success: (res) => {
    if (res.statusCode == 200 && res.tempFilePath.length > 0) {
      pdfPath.value = res.tempFilePath
    }
  }
})
</script>

<style>
.page {
  flex: 1;
}

.viewer {
  flex: 1;
}
</style>

属性

  • url: string PDF 路径(H5支持网络URL,App建议传本地路径)
  • quality: number 清晰度倍率,默认 2,范围 1~4
  • zoom: number 缩放倍率,默认 1,范围 0.5~4
  • mode: string 查看模式:paged(分页) / scroll(滚动)
  • h5Mode: string H5 渲染模式:auto / pdfjs / native,默认 auto
  • h5ViewerPath: string H5 内置 viewer 路径,部署到子目录或自定义静态资源路径时可覆盖

事件

  • load:加载成功
    { errMsg: 'view-pdf:ok' }
  • error:加载失败
    { errMsg: '错误信息' }
  • pageChange:页面切换
    { currentPage: 0, totalPages: 10 }

方法

  • goToPage(pageIndex: number): boolean - 跳转到指定页
  • getCurrentPageIndex(): number | Promise<number> - 获取当前页索引
  • getTotalPages(): number | Promise<number> - 获取总页数

说明

H5 平台

  • 默认使用 PDF.js 渲染,PDF.js 加载失败、跨域失败或超时后自动降级为浏览器原生 iframe 打开
  • h5Mode="pdfjs" 可强制只使用 PDF.js,适合同源或已开启 CORS 的 PDF
  • h5Mode="native" 可跳过 PDF.js,适合远程 PDF 未开启 CORS 但允许浏览器直接访问的场景
  • 若 PDF 服务端既不允许跨域拉取,也不允许 iframe 嵌入,组件会显示“打开 PDF”按钮供用户跳转打开
  • 内置 viewer 默认位于 /uni_modules/view-pdf/static/pdf-viewer/web-viewer.html
  • 部署到非根目录时,如内置 viewer 无法访问,可通过 h5ViewerPath 指定 web-viewer.html 路径

App 平台

  • 使用原生 PDF 渲染组件,性能更好
  • 普通 uni-app App 传入网络 PDF 时会先自动下载到临时文件,再交给原生组件渲染
  • uni-app x App 仍建议业务侧先通过 uni.downloadFile 下载为本地临时文件后再传入
  • Android 使用 PdfRenderer,iOS 使用 PDFKit
  • 若出现空白,优先检查组件容器是否有有效高度

性能优化建议

  • 对于大文件,建议使用 paged 模式
  • 调整 qualityzoom 参数以平衡性能和显示质量
  • Android 端实现了页面缓存机制,提升切换页面的性能

常见问题

Q: H5 端网络 PDF 无法加载?

A: 默认 h5Mode="auto" 会在 PDF.js 失败时降级到浏览器原生 iframe。若仍无法显示,通常是 PDF 服务端限制跨域、TLS 握手或 iframe 嵌入;可尝试 h5Mode="native",或使用后端代理并开启 CORS。

Q: App 端显示空白?

A: 请检查:

  1. 组件容器是否设置了高度
  2. PDF 文件路径是否正确
  3. 文件是否有读取权限

Q: 如何处理大文件?

A: 建议:

  1. 使用 paged 模式而非 scroll 模式
  2. 适当降低 quality 参数
  3. 考虑分片加载

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率: