[Registro de aprendizaje 20] Vue usa blob stream para obtener una vista previa de Word, Excel, pdf, TXT, imágenes y videos

TXT, PDF utilizan directamente el propio navegador para obtener una vista previa

Excel usa el complemento xlsx. Este complemento necesita usar el formato de flujo de arraybuffer. Utilizo la conversión de front-end para consultar el código js para obtener más detalles. También se puede llamar fondo para devolver el flujo de datos de búfer de matriz

Word utiliza el complemento docx-preview

No digas mucho, solo sirve la comida directamente y ajusta el estilo CSS tú mismo.

1. Instale el complemento

  1. npm instala xlsx --guardar

  2. npm instala docx-preview --save

Dos, la parte HTML

<el-dialog
    title="文件预览"
    :visible.sync="dialogVisible"
    fullscreen
    append-to-body
    :before-close="handleClose"
    class="file-dialog">
    <div style="width: 100%;height: 100%;">
      <img v-if="imgUrl" :src="imgUrl" alt="" style="width: 100%;height: 100%">
      <!-- pdf和txt使用iframe -->
      <iframe v-if="pdfUrl" :src="pdfUrl" frameborder="0" style="width: 100%;height: 100%;min-height: 500px;"></iframe>
      <video v-if="videoUrl" :src="videoUrl" controls style="width: 100%;height: 100%;max-height: 800px;"></video>
      <div v-if="docFile">
        <div ref="file"></div>
      </div>
      <div v-if="xlsFile" class="excel-view-container">
        <!-- Excel使用tab选项卡来模拟表格里的sheet业 -->
        <el-tabs type="border-card" v-if="sheetNames && sheetNames.length" @tab-click="handleClick">
          <el-tab-pane :label="item" v-for="(item, index) in sheetNames" :key="index">
            <div class="excelView" v-html="excelView"></div>
          </el-tab-pane>
        </el-tabs>
      </div>
    </div>
  </el-dialog>

Tres, parte js

<script>
  // 定义blob对应的type
  const fileTypeMap = {
    "xls": "application/vnd.ms-excel",
    "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    "doc": "application/msword",
    "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    "pdf": "application/pdf",
    "ppt": "application/pdf",
    "pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
    "png": "image/png",
    "gif": "image/gif",
    "jpeg": "image/jpeg",
    "jpg": "image/jpeg",
    "txt": "text/plain",
  }
  export default {
    data() {
      return {
        imgUrl: '', //图片路径
        pdfUrl: '', //pdf路径
        videoUrl: '', //视频路径
        excelView: '', //表格转换后的html数据
        docFile: false, //是否是word文件
        xlsFile: false, //是否是Excel文件
        execlArraybufferData: null, //Excelblob转换为arraybuff数据
        sheetNames: null, //从数据中获取到的sheet页数组
        imgType: ['bmp', 'jpg', 'jpeg', 'png', 'tif', 'gif', 'pcx', 'tga', 'exif', 'fpx', 'svg', 'psd', 'cdr', 'pcd', 'dxf', 'ufo', 'eps', 'ai', 'raw', 'WMF', 'webp', 'avif', 'apng'],
      videoType: ['wmv', 'asf', 'asx', 'rm', 'rmvb', 'mp4', '3gp', 'mov', 'm4v', 'avi', 'dat', 'mkv', 'flv', 'vob'],
      wordType: ['text', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'rar', 'zip', '7z', 'apz', 'ar', 'bz', 'car', 'dar', 'cpgz', 'f', 'ha', 'hbc', 'hbc2', 'hbe','hpk','hyp'],
      }
    },
    methods: {
      // 获取文件后缀
      getFileType(name) {
        if (name) {
          if (name.lastIndexOf(".") > -1) {
            return name.slice(name.lastIndexOf(".")+1);
          } else {
            return false
          }
        }
      },
      // 预览文件
      filePreviewPDF(path, name) {
        let fileType = this.getFileType(path), url, data
        // 后台接口方法url:接口地址,data给后台传的参数
        this.fileView(url, data).then(res => {
          let type = ''
          if (fileType) {
            type = fileTypeMap[fileType]
            if (this.imgType.includes(fileType)) {
              // 图片类型的
              const blob = new Blob([res], { type })
              this.imgUrl = window.URL.createObjectURL(blob)
            } else if (this.videoType.includes(fileType)) {
              // 视频类型的
              const blob = new Blob([res])
              this.videoUrl = window.URL.createObjectURL(blob)
            } else if (fileType === 'pdf' || fileType === 'txt') {
              // pdf和文本类型的,用iframe打开
              const blob = new Blob([res], { type })
              this.pdfUrl = window.URL.createObjectURL(blob)
            } else if (fileType === 'doc' || fileType === 'docx') {
              // word类型的用docx-preview插件
              this.docFile = true
              let docx = require("docx-preview")
              this.$nextTick(() => {
                docx.renderAsync(res, this.$refs.file).then(x => console.log("docx: finished",x))
              })
            } else if (fileType === 'xls' || fileType === 'xlsx') {
              // 表格类型的用xlsx插件
              this.xlsFile = true
              let XLSX = require("xlsx")
              this.XLSX = XLSX
              this.execlType = type
              let blob = new Blob([res], {type: this.execlType})
              let reader = new FileReader()
              reader.readAsArrayBuffer(blob) // blob类型转换为ArrayBuffer类型
              this.tabChange(0, reader)
            } else {
              this.handleClose()
              this.$modal.msgError('不支持此文件预览')
            }
          } else {
            this.handleClose()
            this.$modal.msgError('不支持此文件预览')
          }
        })
      },
      handleClick(data) {
        this.tabChange(data.index)
      },
      tabChange(index, reader) {
        this.excelView = ''
        let XLSX = this.XLSX
        let _this = this

        // 如果第一次进来
        if (!this.sheetNames) {
          // 文件转换加载完成后
          reader.onload = function() {
            let arraybufferData = this.result
            this.execlArraybufferData = arraybufferData
            let data = new Uint8Array(arraybufferData) // es2017的方法
            let workbook = XLSX.read(data, { type: "array" })  // 得到表格的array数据
            _this.workbooks = workbook  // 赋值到此组件最外面,一会要用
            let sheetNames = workbook.SheetNames; // 得到execl工作表名称集合,结果类似这样['sheet1','sheet2']
            _this.sheetNames = sheetNames  // 赋值到此组件最外面,一会要用
            let worksheet = workbook.Sheets[sheetNames[index]]  // 获取第几个工作表0就是'sheet1',以此类推
            _this['excelView'] = XLSX.utils.sheet_to_html(worksheet) // 把表格的array数据转换成html数据
            _this.$nextTick(function () {
              // DOM加载完毕后执行,解决HTMLConnection有内容但是length为0问题。
              _this.setStyle4ExcelHtml();
            })
          }
        } else {
          // 已经有数据了的时候直接获取对应sheet里的内容
          let worksheet = this.workbooks.Sheets[this.sheetNames[index]];
          this['excelView'] = XLSX.utils.sheet_to_html(worksheet)
        }


      },
      // 设置Excel转成HTML后的样式
      setStyle4ExcelHtml() {
        const excelViewDOM = document.getElementById("excelView");
        if (excelViewDOM) {
          const excelViewTDNodes = excelViewDOM.getElementsByTagName("td"); // 获取的是HTMLConnection
          if (excelViewTDNodes) {
            const excelViewTDArr = Array.prototype.slice.call(excelViewTDNodes);
            for (const i in excelViewTDArr) {
              const id = excelViewTDArr[i].id; // 默认生成的id格式为sjs-A1、sjs-A2......
              if (id) {
                const idNum = id.replace(/[^0-9]/gi, ""); // 提取id中的数字,即行号
                if (idNum && (idNum === "1" || idNum === 1)) {
                  // 第一行标题行
                  excelViewTDArr[i].classList.add("class4Title");
                }
                if (idNum && (idNum === "2" || idNum === 2)) {
                  // 第二行表头行
                  excelViewTDArr[i].classList.add("class4TableTh");
                }
              }
            }
          }
        }
      },
      handleClose() {
        this.$emit('closeDialog', false)
      }
    }
  }
</script>

La idea surge del siguiente enlace;

Vista previa en línea de Vue Word, Excel, PDF, flujo de datos de imágenes La prueba profesional del flujo de archivos de Intranet es efectiva

El archivo de flujo de Excel desde el backend de la vista previa de la página en el flujo de archivos de Excel de vista previa de blog_vue de vue_Familistimo-run.

Supongo que te gusta

Origin blog.csdn.net/wenhui6/article/details/126308083
Recomendado
Clasificación