React实现在线预览word报告/本地选择报告预览

标题使用的核心技术点是docx-preview,读取到文件的File对象,用File去做文件展示,这里是采用将文件转base64字符串存储到localStorage中(如果内容超长,无法存储,可使用在页面直接获取数据的方式,详见第六点)

在线预览word报告且包含word样式

效果展示: https://volodymyrbaydalka.github.io/docxjs

  1. 下载需要使用的min.js文件进项目的public目录中(上zip已包含以下pulib内的js/css文件)
    在这里插入图片描述
    2.在public文件目录下新建html,命名为docpreview.html
    3.在html中引入public下的资源
<link
      href="./docx-preview/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
      crossorigin="anonymous"
    />
    <script
      src="./docx-preview/bootstrap.bundle.min.js"
      integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
      crossorigin="anonymous"
    ></script>
    <script src="./docx-preview/jszip.min.js"></script>
    <script src="./docx-preview/docx-preview.min.js"></script>
    <script src="./docx-preview/thumbnail.example.js"></script>
    <link href="./docx-preview/thumbnail.example.css" rel="stylesheet" />
    <script crossorigin src="./docx-preview/tiff.js"></script>

    <script src="./docx-preview/tiff-preprocessor.js"></script>

4.创建dom去展示对应的docx文件

<body class="vh-100 d-flex flex-column">
    <div class="flex-grow-1 d-flex flex-row" style="height: 0">
      <div
        id="document-container"
        class="overflow-auto flex-grow-1 h-100"
      ></div>
    </div>
  </body>

5.创建一个基于Web的文档查看器,用于查看和预览Microsoft Word文档。

1.获取当前文档(currentDocument):通过document.querySelector(‘#document-container’)获取一个用于显示文档内容的HTML元素。

2.设置docx选项:使用Object.assign()方法将docx.defaultOptions与一个包含debug和experimental属性值的对象进行合并。

3.获取加载按钮(loadButton):通过document.querySelector(‘#loadButton’)获取一个用于加载文档的按钮。

4.定义renderDocx函数:一个异步函数,用于渲染Word文档。它接受一个文件参数(file),将其转换为Blob对象,然后使用docx.renderAsync()方法将其渲染到指定的容器中。同时,它还调用renderThumbnails()函数来生成文档的缩略图。

5.处理加载文档按钮的点击事件:当用户点击加载按钮时,调用renderDocx()函数并传入当前文档

<script>
      let currentDocument = null
      const docxOptions = Object.assign(docx.defaultOptions, {
        debug: true,
        experimental: true
      })

      const container = document.querySelector('#document-container')

      const loadButton = document.querySelector('#loadButton')

      async function renderDocx(file) {
        currentDocument = file
        if (!currentDocument) return
        let docxBlob = preprocessTiff(currentDocument)
        let res = await docx.renderAsync(docxBlob, container, null, docxOptions)
        renderThumbnails(
          container,
          document.querySelector('#thumbnails-container')
        )
      }
    </script>


6.读取本地存储的文件base64并展示

<script>
      // base64Data是从后端接收到的Base64字符串
      const base64String = localStorage.getItem('base64String')

      // 将Base64字符串转换为Blob对象
      const byteCharacters = atob(base64String)
      const byteNumbers = new Array(byteCharacters.length)
      for (let i = 0; i < byteCharacters.length; i++) {
        byteNumbers[i] = byteCharacters.charCodeAt(i)
      }
      const byteArray = new Uint8Array(byteNumbers)
      const blob = new Blob([byteArray], { type: 'application/octet-stream' })

      // 将 Blob 对象转换为 File 对象
      const file = new File([blob], 'example.docx', {
        type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
      })
      //调用方法
      renderDocx(file)
    </script>

在实验中,发现文章太长可能会导致存储超长,可以使用一下方法解决:
核心点:直接使用接口返回,在html中直接读取数据,页面添加loading

fetch(
          `接口api`,
          {
            method: 'GET'
          }
        )
          .then((resp) => resp.json())
          .then((response) => {
            const base64String = response?.data
            // 将Base64字符串转换为Blob对象
            const byteCharacters = atob(base64String)

7.触发预览按钮的事件

  //预览报告
  function previewReportRequest() {
    setsubmitLoading(true)
    asyncActionCreators.previewReport({ id: ID }).then((response) => {
      setsubmitLoading(false)
      if (response?.data?.code === 0) {
        localStorage.setItem('base64String', response?.data?.data)
        //存好之后,跳转到预览页面
        const htmlFilePath = `${window.location.origin}/docpreview.html`
        openHtmlFileInNewTab(htmlFilePath)
      } else {
        message.warning(response.data.msg || '获取报告失败')
      }
    })
  }


  const openHtmlFileInNewTab = (url) => {
    const anchor = document.createElement('a')
    anchor.href = url
    anchor.target = '_blank'
    anchor.rel = 'noopener noreferrer'
    anchor.click()
  }

本地选择文件后预览需做以下改动

1.设一个input选取文件

<input type="file" accept=".docx" onChange={handleLocalFilePreview} />

2.添加文件选择方法

const handleLocalFilePreview = (event) => {
    const file = event.target.files[0]
    const reader = new FileReader()
    // 将 Blob 数据编码为 Base64 字符串
    reader.onload = (event) => {
      const base64String = event.target.result
      localStorage.setItem('base64String', base64String)
    }
    reader.readAsDataURL(file)
  }

3.预览按钮的事件 openHtmlFileInNewTab同在线预览

  const docxPreview = () => {
    const htmlFilePath = `${window.location.origin}/docpreview.html`
     openHtmlFileInNewTab(htmlFilePath)
  }

4.html文件需要改变方法

<script>
      //==========之前的===========
      //获取存储的blob的base64字符串
       const base64String = localStorage.getItem('base64String')
       // 将 Base64 字符串解码为 Blob 对象
       const byteCharacters = atob(base64String?.split(',')?.[1])
       const byteNumbers = new Array(byteCharacters.length)
       for (let i = 0; i < byteCharacters.length; i++) {
         byteNumbers[i] = byteCharacters.charCodeAt(i)
       }
       const byteArray = new Uint8Array(byteNumbers)
       const blob = new Blob([byteArray])
       const file = new File([blob], 'example.docx', {
         type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
      })

      // 将 Blob 对象转换为 File 对象
      const file = new File([blob], 'example.docx', {
        type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
      })
      //调用方法
      renderDocx(file)
    </script>
  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值