This is the 8th day of my participation in the August More Text Challenge. For details, see:August is more challenging

preface

Recently developed an architecturally related mobile project with various accessory preview capabilities. Through various attempts, some commonly used file preview methods are summarized. This article provides previews of vuE3 commonly used files (PDF, Word, Excel, TXT).

A PDF preview

The PDF preview used in this article was via the PDfjS-dist plug-in, which was used in Vue3 with some bugs.

  • First of all bynpmInstalling a plug-in
npm install --save pdfjs-dist
Copy the code
  • Then introduce it in the page
const PDF = require('pdfjs-dist')
Copy the code
  • After starting the project, the following error will be reported:

Take a closer look at the error message, is the plugin using ES11 syntax? However, when the project starts, the code in the plug-in is not compiled, causing the project to fail to start. The solution is to configure WebPack in your project to compile against this plug-in.

Change the project root directory to vue.config.js, if not, create one and add the following code to the file:

// vue.config.js
module.exports = {
  // ...
  chainWebpack: config= > {
     // ...
     config.module.rule('pdfjs-dist').test({
      test: /\.js$/,
      include: path.join(__dirname, 'node_modules/pdfjs-dist')
    }).use('babel-loader').loader('babel-loader').options({
      presets: ['@babel/preset-env'].plugins: ['@babel/plugin-proposal-optional-chaining']})}}Copy the code
  • Later mistakes

Need to configure workerSrc after introducing PDFJS – dist, but introducing PDFJS – dist/build/PDF. Worker. After entry the browser or a Warning: Warning: Setting up fake worker. After searching for various reasons, I finally found a description: PDF.worker.js must be in its own file (not bundled with PDF.js). Otherwise it cannot run in the service worker thread.

Make a copy of pdfjs-dist/build/pdf.worker.js and put it in the public directory of the project.

  • PDF parses component code

    Load the PDF file through PDfjS-dist, get the total number of pages, traverse the canvas to the page, and then write a recursive function to parse each page of the PDF through getPage to render the PDF content to the canvas. The following example encapsulates a parsed PDF component to render the PDF in full screen by passing a file link.

<template>
  <div class="pdf">
    <template v-for="item in pageNum" :key="item">
      <canvas :id="`pdf-canvas-${item}`" class="pdf-page" />
    </template>
  </div>
</template>
<script>
import { reactive, toRefs, nextTick, watchEffect } from 'vue'
const PDF = require('pdfjs-dist')
PDF.GlobalWorkerOptions.workerSrc = '/pdf.worker.js'
export default {
  name: 'DisplayPdf'.props: {
    url: {
      type: String.default: ' '
    }
  },
  setup (props, { emit }) {
    const state = reactive({
      pageNum: 0.pdfCtx: null
    })
    watchEffect(() = > {
      if (props.url) {
        resolvePdf(props.url)
      }
    })
    const resolvePdf = (url) = > {
      const loadingTask = PDF.getDocument(url)
      loadingTask.promise.then(pdf= > {
        state.pdfCtx = pdf
        state.pageNum = pdf.numPages
        nextTick(() = > {
          renderPdf()
        })
      })
    }
    const renderPdf = (num = 1) = > {
      state.pdfCtx.getPage(num).then(page= > {
        const canvas = document.getElementById(`pdf-canvas-${num}`)
        const ctx = canvas.getContext('2d')
        const viewport = page.getViewport({ scale: 1 })
        // Canvas size, default width:300px,height:150px
        canvas.height = viewport.height
        canvas.width = viewport.width
        // The canvas dom size, set the mobile end, width set to cover the entire screen
        const clientWidth = document.body.clientWidth
        canvas.style.width = clientWidth + 'px'
        // Set canvas height according to the width/height ratio of each PDF page
        canvas.style.height = clientWidth * (viewport.height / viewport.width) + 'px'
        page.render({
          canvasContext: ctx,
          viewport
        })
        if (num < state.pageNum) {
          renderPdf(num + 1)}else {
          emit('onRendered')}}}return {
      ...toRefs(state)
    }
  }
}
</script>
Copy the code

Two, TXT file preview

TXT file preview is relatively simple, because there is no style, we directly read the contents of the file, display to the page.

White-space: pre-wrap; white-space: pre-wrap; white-space: pre-wrap; , or replace all the newlines in the content with

using V-HTML to display the content.

<template>
  <div class="txt" style="white-space: pre-wrap;">{{ txtContent }}</div>
</template>
<script>
import { ref } from 'vue'
import axios from 'axios'
export default {
  name: 'PreviewTxt',
  setup () {
    const txtContent = ref(' ')
    const url = '/demo.txt'
    axios.get(url, {
      responseType: 'text'
    }).then(res= > {
      txtContent.value = res.data
    })
    return {
      txtContent
    }
  }
}
</script>
Copy the code

3. Word preview

In this paper, mammoth. Js is used, and complex styles are ignored, but simple content preview is implemented. The use method is also very simple: obtain the file’s ArrayBuffer through HTTP request, and then convert the content into HTML using mammoth. If the file to the network access and confidentiality is not high, and it is recommended to use http://view.officeapps.live.com/op/view.aspx?src= preview document url.

// npm install mammoth --save
<template>
  <div class="word-container" v-html="doc" />
</template>
<script>
import { watchEffect, ref } from 'vue'
import axios from 'axios'
import mammoth from 'mammoth'
export default {
  name: 'DisplayDocx'.props: {
    url: {
      type: String.default: ' '
    }
  },
  setup (props) {
    const doc = ref(' ')
    const resolveDocx = async (url) => {
      const { data } = await axios.get(url, { responseType: 'arraybuffer' })
      const res = await mammoth.convertToHtml({ arrayBuffer: data })
      doc.value = res.value
    }
    watchEffect(() = > {
      if (props.url) resolveDocx(props.url)
    })
    return { doc }
  }
}
</script>
Copy the code

4. Excel Preview

The Excel preview uses the XSLS plug-in to read the contents of a Sheet of a file, and then convert the contents into JSON. We render the table in JSON ourselves.

npm install xsls --save
Copy the code

Read out json content as follows, default to the first behavior key.

This can also be changed with the second parameter of sheet_to_JSON, which returns an array of rows from each behavior file if {header: 1} is passed

The sample code

import xlsx from 'xlsx'
import axios from 'axios'
export default {
  name: 'PreviewExcel'.async setup () {
    const url = '/demo.xlsx'
    const { data } = await axios.get(url, { responseType: 'arraybuffer' })
    const ctx = xlsx.read(data, { type: 'array' })
    const result = xlsx.utils.sheet_to_json(ctx.Sheets[ctx.SheetNames[0]] and {header: 1 })
    console.log(result)
  }
}
Copy the code