Front-end implementation of file preview (pdf, excel, word, pictures)

Front-end implementation of file preview function

Requirements: Realize an online preview function of pdf, excel, word, pictures and other files.
Introduction: Support pdf, xlsx, docx, jpg, png, jpeg.
The following uses Vue3 code to implement all functions. It is recommended that the following preview file tags can be wrapped with a pop-up window on the outer layer.

Picture Preview 

<iframe  :src="图片地址"
         style="z-index: 1000; height:650px; width: 100%; margin: 0 auto"
         sandbox="allow-scripts allow-top-navigation allow-same-origin allow-popups"
>

The attribute sandbox can be ignored if it is a simple preview image. This attribute enables some additional restrictions on the content presented in the iframe frame. The property value can be an empty string (in which case all restrictions are enabled), or a series of specified strings separated by spaces.

  • allow-scripts: Allows the embedded browsing context to run scripts (but not create popups). If this keyword is not used, the script cannot be run.
  • allow-top-navigation: Allows hyperlinks in pages loaded within a frame to navigate to the parent window
  • allow-same-popups: Allow popups (eg window.open, target="_blank"). If this keyword is not used, the corresponding function will be automatically disabled.
  • allow-same-origin: If this keyword is not used, the embedded browsing context will be treated as coming from a separate origin, which will fail the same-origin policy check. If this attribute is used, the current page and the page opened by the iframe are considered to be of the same origin.

word document preview (docx)

先下载npm包
npm i docx-preview --save
<div class="docxRef"></div>

<script>
import { renderAsync } from 'docx-preview';

function fn() {
// 这里的res.data是 blob文件流,如果自己的不是blob文件流
// 可以通过URL.createObjectURL(参数) 参数为File格式,转换为blob文件流
    let blob = res.data
    let childRef = document.getElementsByClassName('docxRef');
    renderAsync(blob, childRef[0]) //渲染
}
fn()

</script>

blob file stream

 Preview excel file (xlsx)

下载包
npm install [email protected]
<div class="xlsxClass"></div>

const reader = new FileReader();
//通过readAsArrayBuffer将blob转换为ArrayBuffer对
reader.readAsArrayBuffer(res.data) // 这里的res.data是blob文件流
reader.onload = (event) => {
  // 读取ArrayBuffer数据变成Uint8Array
  var data = new Uint8Array(event.target.result);
  // 这里的data里面的类型和后面的type类型要对应
  var workbook = XLSX.read(data, { type: "array" });
  var sheetNames = workbook.SheetNames; // 工作表名称
  var worksheet = workbook.Sheets[sheetNames[0]];
  // var excelData = XLSX.utils.sheet_to_json(worksheet); //JSON
  let html = XLSX.utils.sheet_to_html(worksheet);
  document.getElementsByClassName('xlsxClass')[0].innerHTML = html
};

pdf preview

下载包 npm install pdfjs-dist
我使用的是npm install [email protected]版本,以下例子使用的是vue3+vite创建的项目
以下例子通过canvas来渲染pdf
<template>
  <div class="box">
    <div class="tool-bar">
      <div>{
   
   { pdfParams.pageNumber }} / {
   
   { pdfParams.total }}</div>
      <button type="primary" :disabled="pdfParams.pageNumber == pdfParams.total" @click="nextPage">下一页
      </button>
      <button type="primary" :disabled="pdfParams.pageNumber == 1" @click="prevPage">上一页</button>
    </div>
    <canvas id="pdf-render"></canvas>
  </div>
</template>

<script setup>
import { onMounted, ref, reactive } from 'vue'
const pdfParams = reactive({
  pageNumber: 1, // 当前页
  total: 0, // 总页数
});

// 不要定义为ref或reactive格式,就定义为普通的变量
let pdfDoc = null;
// 这里必须使用异步去引用pdf文件,直接去import会报错,也不知道为什么
onMounted(async ()=> {
  let pdfjs = await import('pdfjs-dist/build/pdf')
  let pdfjsWorker = await import('pdfjs-dist/build/pdf.worker.entry')
  pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker
  // 此文件位于public/test2.pdf
  let url = ref('/test2.pdf')
  pdfjs.getDocument(url.value).promise.then(doc => {
    pdfDoc = doc
    pdfParams.total = doc.numPages
    getPdfPage(1)
  })
})

// 加载pdf的某一页
const getPdfPage = (number) => {
  pdfDoc.getPage(number).then(page => {
    const viewport = page.getViewport()
    const canvas = document.getElementById('pdf-render')
    const context = canvas.getContext('2d')
    canvas.width = viewport.viewBox[2]
    canvas.height = viewport.viewBox[3]
    viewport.width = viewport.viewBox[2]
    viewport.height = viewport.viewBox[3]
    canvas.style.width = Math.floor(viewport.width) + 'px'
    canvas.style.height = Math.floor(viewport.height) + 'px'

    let renderContext = {
      canvasContext: context,
      viewport: viewport,
      // 这里transform的六个参数,使用的是transform中的Matrix(矩阵)
      transform: [1, 0, 0, -1, 0, viewport.height]
    }
    // 进行渲染
    page.render(renderContext)
  })
}
// 下一页功能
const prevPage = () => {
  if(pdfParams.pageNumber > 1) {
    pdfParams.pageNumber -= 1
  } else {
    pdfParams.pageNumber  = 1
  }
  getPdfPage(pdfParams.pageNumber)
}
// 上一页功能
const nextPage = () => {
  if(pdfParams.pageNumber < pdfParams.total) {
    pdfParams.pageNumber += 1
  } else {
    pdfParams.pageNumber = pdfParams.total
  }
  getPdfPage(pdfParams.pageNumber)
}
</script>

The above pdf code quotes the article: (54 messages) Front-end pdf preview, use of pdfjs_pdf.js_ignorant rookie's blog-CSDN blog
pdfjs official code: Example (mozilla.github.io)
The above code cannot be understood You can check the official code in the local area, most of which are fixed.

Points to note above:

  • Files in pdf must be referenced asynchronously! ! !
  • The pdf demo file is located at public/test2.pdf
  • transform: [1, 0, 0, -1, 0, viewport.height], using the Matrix in transform
  • Both the next page and previous page functions need to be re-rendered

Guess you like

Origin blog.csdn.net/autumnmn/article/details/131311840