最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

uni-app安卓端純前端預(yù)覽DOCX的實現(xiàn)思路及代碼實例

 更新時間:2026年05月14日 11:02:41   作者:Amy_yang  
在移動應(yīng)用開發(fā)中,文件預(yù)覽功能幾乎成為標(biāo)配需,這篇文章主要介紹了uni-app安卓端純前端預(yù)覽DOCX的實現(xiàn)思路及代碼實例的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在 uni-app 項目中,docx 文件預(yù)覽看起來像是一個簡單需求,但在安卓 App 環(huán)境下會遇到不少坑。

本文結(jié)合當(dāng)前項目的實現(xiàn),說明為什么不能直接在頁面中渲染 docx,以及如何通過 docx-preview + 本地 web-view 實現(xiàn)純前端預(yù)覽。

一、DOCX 為什么可以純前端預(yù)覽

docx 本質(zhì)上不是傳統(tǒng)二進(jìn)制文件,而是一個壓縮包。

它內(nèi)部主要包含:

  • XML 文檔內(nèi)容
  • 樣式文件
  • 圖片資源
  • 字體、編號、頁眉頁腳等配置

所以前端可以通過 JS 解壓并解析這些 XML,再渲染成 HTML。

常見純前端庫有:

  • docx-preview
  • mammoth.js

其中:

  • docx-preview 更偏向“還原 Word 頁面效果”
  • mammoth.js 更偏向“提取正文內(nèi)容”

如果目標(biāo)是“預(yù)覽文檔”,更推薦使用 docx-preview

二、為什么 DOC 不能一樣處理

doc 是老版本 Word 二進(jìn)制格式,不是 zip + XML 結(jié)構(gòu)。

瀏覽器端沒有成熟穩(wěn)定的純 JS 方案可以完整解析 .doc 文件。

所以:

docx -> 可以嘗試純前端預(yù)覽
doc  -> 不建議純前端預(yù)覽

對于 .doc,更推薦:

  • 后端轉(zhuǎn) PDF
  • 調(diào)用系統(tǒng)應(yīng)用打開
  • 使用文檔服務(wù)或原生插件

三、為什么不能直接在 uni-app 頁面里渲染

一開始最容易想到的寫法是:

import { renderAsync } from 'docx-preview';

const renderDocx = async () => {
  const bodyEl = document.getElementById('docxBodyBox');

  await renderAsync(buffer, bodyEl);
};

在 H5 里這通常沒問題。

但在 uni-app 安卓 App 端,普通頁面里的 <script setup> 并不是穩(wěn)定的瀏覽器 DOM 執(zhí)行環(huán)境。

常見問題包括:

  • document 不存在
  • document.getElementById() 找不到容器
  • DOM 已渲染但原生層還沒準(zhǔn)備好
  • 文件讀取能力和瀏覽器 H5 不一致

因此,直接在 filePreview.vue 里使用 docx-preview,在安卓 App 端并不可靠。

四、最終方案:本地 HTML + web-view

更穩(wěn)的方案是:

uni-app 頁面
-> web-view 打開本地 viewer.html
-> viewer.html 加載 docx-preview
-> viewer.html 下載或讀取 docx 文件
-> docx-preview 渲染 HTML

也就是說,把 docx-preview 放到真正的 WebView 頁面里執(zhí)行。

項目結(jié)構(gòu)示例:

static/docx-preview/
├── viewer.html
├── docx-preview.min.js
└── jszip.min.js

其中:

  • viewer.html 是本地預(yù)覽頁面
  • docx-preview.min.js 是預(yù)覽庫
  • jszip.min.js 是 docx 解壓依賴

五、App 頁面如何打開 DOCX 預(yù)覽

filePreview.vue 中,docx 文件走單獨分支:

<view v-else-if="isDocxFile" class="docx-preview-container">
  <!-- #ifdef APP-PLUS -->
  <view v-if="docxRendering" class="preview-loading">
    <view class="loading-spinner"></view>
    <text class="loading-text">文檔下載中...</text>
  </view>
  <view v-else-if="docxRenderError" class="preview-error">
    <text class="error-text">{{ docxRenderError }}</text>
    <view class="retry-btn" @click="prepareAppDocxPreview">重新加載</view>
    <view class="retry-btn secondary" @click="previewWithSystemViewer">
      系統(tǒng)應(yīng)用打開
    </view>
  </view>
  <view v-else class="app-native-preview">
    <web-view
      :src="getDocxViewerUrl"
      class="docx-webview"
      :fullscreen="false"
      style="width: 100%; height: 100%; border: 0"
      :webview-styles="{
        width: '100%',
        height: '100%',
        progress: { color: '#16a5fb' }
      }"
    ></web-view>
  </view>
  <!-- #endif -->
</view>

預(yù)覽地址:

const getDocxViewerUrl = computed(() => {
  const previewUrl = docxLocalPath.value || fileInfo.value.url;
  if (!previewUrl) return '';
  return `/static/docx-preview/viewer.html?file=${encodeURIComponent(previewUrl)}`;
});

六、為什么要先用 uni.downloadFile 下載

一開始可以讓 viewer.html 自己下載遠(yuǎn)程 docx

fetch(fileUrl)

或:

plus.downloader.createDownload(fileUrl)

但在真實項目中經(jīng)常會失?。?/p>

  • 文件地址需要登錄態(tài)
  • 下載接口需要 token
  • 本地 HTML 不一定能拿到業(yè)務(wù)請求頭
  • 遠(yuǎn)程文件可能有跨域限制
  • plus.downloader 在 web-view 內(nèi)部回調(diào)不穩(wěn)定

所以更穩(wěn)的方式是:

filePreview.vue 用 uni.downloadFile 下載
-> 帶上 token
-> 拿到 tempFilePath
-> 傳給 viewer.html

代碼示例:

const prepareAppDocxPreview = () => {
  docxLocalPath.value = '';
  docxRenderError.value = '';
  docxRendering.value = true;

  uni.downloadFile({
    url: fileInfo.value.url,
    header: {
      token: uni.getStorageSync('token') || ''
    },
    success: (res) => {
      docxRendering.value = false;

      if (res.statusCode !== 200 || !res.tempFilePath) {
        docxRenderError.value = `文檔下載失敗: ${res.statusCode || '未知錯誤'}`;
        return;
      }

      try {
        docxLocalPath.value =
          plus.io.convertLocalFileSystemURL(res.tempFilePath) ||
          res.tempFilePath;
      } catch (error) {
        docxLocalPath.value = res.tempFilePath;
      }
    },
    fail: () => {
      docxRendering.value = false;
      docxRenderError.value = '文檔下載失敗,請檢查文件地址或權(quán)限';
    }
  });
};

七、viewer.html 如何渲染 DOCX

viewer.html 需要先加載依賴:

<script src="./jszip.min.js"></script>
<script src="./docx-preview.min.js"></script>

然后讀取文件并渲染:

await window.docx.renderAsync(
  buffer,
  document.getElementById('docxBodyBox'),
  document.getElementById('docxStyleBox'),
  {
    className: 'docx-rendered',
    inWrapper: true,
    ignoreWidth: false,
    ignoreHeight: false,
    ignoreFonts: false,
    breakPages: true,
    experimental: false,
    useBase64URL: true
  }
);

八、本地文件讀取的坑

安卓 App 端下載后的路徑可能是:

_doc/uniapp_temp_xxx/download/xxx.docx

也可能被轉(zhuǎn)換成:

/storage/emulated/0/Android/data/xxx/xxx.docx

這些路徑不是標(biāo)準(zhǔn)瀏覽器 URL。

常見坑包括:

1. FileReader 不能讀取 plus.io 的 File 對象

錯誤示例:

Failed to execute 'readAsArrayBuffer' on 'FileReader':
parameter 1 is not of type 'Blob'

原因是 Android WebView 里的 plus.io File 對象不一定是標(biāo)準(zhǔn) Blob。

2. XHR 不能直接讀取_doc/...

錯誤示例:

read local file failed

原因是 _doc/... 是 5+ 私有路徑,不是普通瀏覽器可直接訪問路徑。

3. 需要多路徑兜底

所以讀取本地文件時,需要嘗試多種路徑:

  • entry.nativeURL
  • entry.toLocalURL()
  • entry.toURL()
  • _doc/...
  • /storage/...
  • file:///storage/...

示例邏輯:

function readLocalByPlus(fileUrl) {
  return new Promise(function(resolve, reject) {
    plus.io.resolveLocalFileSystemURL(fileUrl, function(entry) {
      const paths = [];

      if (entry.nativeURL) paths.push(entry.nativeURL);
      if (typeof entry.toLocalURL === 'function') paths.push(entry.toLocalURL());
      if (typeof entry.toURL === 'function') paths.push(entry.toURL());

      paths.push(fileUrl);

      readFirstAvailablePath(paths).then(resolve).catch(reject);
    }, reject);
  });
}

九、web-view 全屏問題

在安卓 App 端,web-view 是原生子窗口,不是普通 DOM 節(jié)點。

所以僅寫:

width: 100%;
height: 100%;

不一定能限制它的真實大小。

需要通過當(dāng)前頁面的原生子 WebView 設(shè)置尺寸:

const childWebview = currentWebview.children()[0];

childWebview.setStyle({
  top: Math.round(rect.top),
  left: Math.round(rect.left),
  width: Math.round(rect.width),
  height: Math.round(rect.height)
});

這樣才能避免 docx 預(yù)覽的 web-view 在安卓端覆蓋全屏。

十、最終鏈路總結(jié)

當(dāng)前推薦鏈路是:

用戶打開 docx 文件
-> filePreview.vue 判斷是 docx
-> uni.downloadFile 帶 token 下載文件
-> 得到本地 tempFilePath
-> 轉(zhuǎn)換本地路徑
-> web-view 打開 static/docx-preview/viewer.html?file=本地路徑
-> viewer.html 讀取本地 docx
-> docx-preview 渲染 HTML

這套方案的特點:

  • 不依賴后端轉(zhuǎn) PDF
  • 不依賴 Office Online
  • 不依賴 X5 插件
  • 屬于純前端預(yù)覽
  • 只支持 .docx
  • .doc 仍然需要系統(tǒng)應(yīng)用或后端轉(zhuǎn)換

十一、局限性

docx-preview 不是 Word 官方內(nèi)核,因此存在一些限制:

  • 復(fù)雜頁眉頁腳可能不完全一致
  • 批注、修訂痕跡支持有限
  • 特殊字體可能不一致
  • 復(fù)雜表格可能變形
  • 大文件渲染慢
  • 加密文檔不支持
  • .doc 不支持

所以它適合“在線預(yù)覽”,不適合對版式要求極高的正式排版校驗。

十二、結(jié)論

在 uni-app 安卓 App 端,docx 純前端預(yù)覽不能簡單地把 docx-preview 寫在頁面腳本里。

更穩(wěn)的方式是:

docx-preview 放到本地 HTML
通過 web-view 執(zhí)行
App 頁面負(fù)責(zé)下載和傳遞本地文件路徑
viewer 頁面負(fù)責(zé)解析和渲染

一句話總結(jié):

DOCX 可以純前端預(yù)覽,但在 App 端必須把渲染放到真正的 WebView 環(huán)境里處理。

到此這篇關(guān)于uni-app安卓端純前端預(yù)覽DOCX的實現(xiàn)思路及代碼實例的文章就介紹到這了,更多相關(guān)uni-app安卓端純前端預(yù)覽DOCX內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺聊一下為什么能用RxJS取代Redux

    淺聊一下為什么能用RxJS取代Redux

    本文我們將和大家淺聊一下為什么能用RxJS取代Redux,RxJS 在現(xiàn)在的前端用比較少,但是 RxJS 作為響應(yīng)式和函數(shù)式編程的集大成者,似乎被前端開發(fā)者遺忘,可能是學(xué)習(xí)難度大,可能是有更加方便的解決方案,需要的朋友可以參考下
    2024-02-02
  • JavaScript中exec函數(shù)用法實例分析

    JavaScript中exec函數(shù)用法實例分析

    這篇文章主要介紹了JavaScript中exec函數(shù)用法,較為詳細(xì)的分析了javascript中exec函數(shù)的功能、定義及使用方法,需要的朋友可以參考下
    2015-06-06
  • js 事件處理函數(shù)間的Event物件是否全等

    js 事件處理函數(shù)間的Event物件是否全等

    在非IE,事件對象Propagation之間的處理函數(shù),或同dom節(jié)點觸發(fā)的多個函數(shù)之間的Event物件是全等的。與綁定形式[addEventListener/DOM0]無關(guān)。
    2011-04-04
  • JavaScript函數(shù)、方法、對象代碼

    JavaScript函數(shù)、方法、對象代碼

    函數(shù)定義可以嵌套在其他函數(shù)中,常用作子函數(shù)。但不能出現(xiàn)在循環(huán)或條件語句中。
    2008-10-10
  • 超贊的動手創(chuàng)建JavaScript框架的詳細(xì)教程

    超贊的動手創(chuàng)建JavaScript框架的詳細(xì)教程

    這篇文章主要介紹了動手創(chuàng)建JavaScript框架的詳細(xì)教程,包括DOM和各種屬性的調(diào)試等各個方面,超級推薦!需要的朋友可以參考下
    2015-06-06
  • js數(shù)組去重的11種方法

    js數(shù)組去重的11種方法

    這篇文章主要介紹了js數(shù)組去重的11種方法,對js數(shù)組感興趣的同學(xué),可以把這11種方法實驗一下
    2021-04-04
  • javascript刷新父頁面方法匯總詳解

    javascript刷新父頁面方法匯總詳解

    這篇文章主要介紹了javascript刷新父頁面方法匯總詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • Json按某個鍵的值進(jìn)行排序

    Json按某個鍵的值進(jìn)行排序

    這篇文章主要介紹了json按某個鍵的值進(jìn)行排序的相關(guān)資料,代碼簡單易懂,非常不錯,需要的朋友可以參考下
    2016-12-12
  • JS中的hasOwnProperty()、propertyIsEnumerable()和isPrototypeOf()

    JS中的hasOwnProperty()、propertyIsEnumerable()和isPrototypeOf()

    這篇文章主要介紹了JS中的hasOwnProperty()、propertyIsEnumerable()和isPrototypeOf()的相關(guān)資料,需要的朋友可以參考下
    2016-08-08
  • JavaScript 字符串常用操作小結(jié)(非常實用)

    JavaScript 字符串常用操作小結(jié)(非常實用)

    這篇文章主要介紹了JavaScript 字符串常用操作的知識,包括字符串截取,查找類的方法,對js字符串操作相關(guān)知識感興趣的朋友一起學(xué)習(xí)吧
    2016-11-11

最新評論

盐边县| 东阿县| 日土县| 勐海县| 大荔县| 拜城县| 金平| 萨嘎县| 青岛市| 靖宇县| 天等县| 利川市| 汤原县| 巩义市| 林周县| 达日县| 怀仁县| 库尔勒市| 修水县| 乐至县| 通化县| 云阳县| 北流市| 静乐县| 自治县| 辉县市| 阜新市| 宁明县| 中江县| 新乡市| 高青县| 荆门市| 朝阳区| 邯郸县| 东兰县| 湘潭县| 嵩明县| 固安县| 获嘉县| 濮阳市| 青海省|