VUE系列---VUE+indexDB+JSZip+在线预览zip压缩文件(三)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/nongshuqiner/article/details/64922395

温馨连接提示:vue中级之路篇系列教程:
VUE系列—VUE+indexDB+JSZip+在线预览zip压缩文件(一)
VUE系列—VUE+indexDB+JSZip+在线预览zip压缩文件(二)
VUE系列—VUE+indexDB+JSZip+在线预览zip压缩文件(三)

注:请看完前两篇再来,不然你看不懂

通过前两篇文章我们的项目已经做出来了文件预览的初始效果,不知道你们看了以后会有什么想法,这篇文章开始着重讲解文件系统的构建。

####前言

前面我们已经得到文件树对象了,现在我们所要做的就是页面的功能实现,我们读取并在indexDB数据库里存储了文件信息,为了解决直接渲染文件信息到页面上,浏览器崩溃的问题,我们没有直接进行读取,而是采用创建目录,进去了以后在打开某一个具体的文件时,读取这个具体文件这一个单独的文件时,这样读取的息量少,所以不会崩溃。

但是有个问题,我们怎么去取这个文件信息,或者说我们怎么在indexDB数据库里准确找到这个文件信息?因为indexDB的特殊性我们不能去遍历它,不是不能遍历而是因为他的遍历机制太耗时间,每次打开一个文件遍历一次这样不妥,所以我们需要在给indexDB数据库添加文件信息时,记录文件信息对应它的存储索引。

##文件预览初始

起初,我想的是建一个数组,zip.forEach每执行一次,就往里面添加一个路径信息(即:01借款人申请表资料/实例/申请表与工作证0.jpg),再通过他在数组中的位置来对应记录其在indexDB数据库中的索引,通过indexDB的objectStore.get()直接就可以得到相应信息。但是我们的zip.forEach里面有好几个异步函数,没有人知道它具体何时能执行完,于是,就继续使用对象的方式记录。记录完后,我们需要渲染页面了,对于不同的文件,做成不同的样子,同时,为了优化,我们不能退出了数据库还在,所以在返回时数据库会被删除。

于是,我们把/page/property/upload_review.vue文件最终的代码附上:

“`js





<a :download="this.curfile_infor.file_name" :href="requestfileinfor" @click="downloadExcel(curfile_infor.file_content)">
    <el-button type="primary" size="mini">下载表格</el-button>
</a>

由于我们使用base64编码方式存储的二进制信息,所以得把二进制信息转换为文件信息:

downloadExcel (filecontent) {
     this.requestfileinfor = 'data:application/vnd.ms-excel;base64,' + filecontent
}

data:application/vnd.ms-excel;base64,是一种二进制变为文件的方式。
我们需要返回到上一级目录,所以我们保存的当前目录的分支及层级就拍上用场:

gotoBack () {
      window.localStorage.curFileBranchHierarchy-- // 减层级
      var curFileBranchPath = window.localStorage.curFileBranchPath
      var fileObj = JSON.parse(window.localStorage.file_obj)
      if (curFileBranchPath.indexOf('/') !== -1) { // 判断有无/,如果无则是最顶级,清空所有与目录相关的
        var pathArray = curFileBranchPath.split('/') // 减当前目录路径
        var curFilePath = ''
        var curFileObjBranch = {} // 获取当前文件父级对象分支
        for (var i = 0; i < pathArray.slice(0, pathArray.length - 1).length; i++) {
          if (curFilePath === '') {
            curFilePath = pathArray.slice(0, pathArray.length - 1)[i]
          } else {
            curFilePath = curFilePath + '/' + pathArray.slice(0, pathArray.length - 1)[i]
          }
          if (!this.$task.judgeIsNullObj(curFileObjBranch)) { // 初始时直接file_obj赋值
            curFileObjBranch = fileObj[pathArray.slice(0, pathArray.length - 1)[0]]
          } else {
            // 不是初始值在curFileObjBranch中取
            curFileObjBranch = curFileObjBranch[pathArray.slice(0, pathArray.length - 1)[i]]
          }
        }
        window.localStorage.curFileBranchPath = curFilePath
        window.localStorage.curFileObjBranch = JSON.stringify(curFileObjBranch)
      } else {
        window.localStorage.removeItem('curfileIndexDbIndexObj')
        window.localStorage.removeItem('curFileObjBranch')
        window.localStorage.removeItem('curFileBranchPath')
        window.localStorage.removeItem('curFileBranchHierarchy')
      }
      this.$router.go(-1)
}

我们也把/page/property/upload_review_details.vue文件最终的代码附上:

<template>
  <div>
    <!-- top -->
    <section class="admin_tool">
      <div class="admin_tool_btn">
        <el-button size="small" @click="gotoBack">
          <i class="fa-chevron-left"></i>
          <span>返回</span>
        </el-button>
      </div>
      <div class="admin_location">
        <el-breadcrumb>
          <el-breadcrumb-item>zip在线预览</el-breadcrumb-item>
        </el-breadcrumb>
      </div>
    </section>
    <section class="file_review">
      <h3>文件预览</h3>
      <span class="file_breadcrumb" v-text="breadcrumb"></span>
      <ul class="file_review_list">
        <li class="file_list_other" v-for="(value, keys, index) in curFileObjBranch" @click="selectedFile($event)" @dblclick="openfile(value, keys)">
          <template v-if="fileTypeNameJudge(keys).file_type === 'photo' && fileTypeNameJudge(keys).file_status === 0">
            <i class="icon_photo"></i>
            <span v-text="keys"></span>
          </template>
          <template v-if="fileTypeNameJudge(keys).file_type === 'excel' && fileTypeNameJudge(keys).file_status === 0">
            <i class="icon_excel"></i>
            <span v-text="keys"></span>
          </template>
          <template v-if="fileTypeNameJudge(keys).error_name === '无法识别此文件' && fileTypeNameJudge(keys).file_status === 0">
            <i class="icon_errorfile"></i>
            <span v-text="keys"></span>
          </template>
          <template v-if="fileTypeNameJudge(keys).file_type === 'dir' && fileTypeNameJudge(keys).file_status === 1">
            <i class="icon_finder"></i>
            <span v-text="keys"></span>
          </template>
        </li>
      </ul>
    </section>
  </div>
</template>
<script>
export default {
  data () {
    return {
      file_obj: {},
      zipfile_index: {},
      curFileObjBranch: [],
      imgUrlArr: null,
      breadcrumb: this.$store.get('curFileBranchPath')
    }
  },
  created () {
    this.getBaseData()
  },
  methods: {
    gotoBack () {
      window.localStorage.curFileBranchHierarchy-- // 减层级
      var curFileBranchPath = window.localStorage.curFileBranchPath
      var fileObj = JSON.parse(window.localStorage.file_obj)
      if (curFileBranchPath.indexOf('/') !== -1) { // 判断有无/,如果无则是最顶级,清空所有与目录相关的
        var pathArray = curFileBranchPath.split('/') // 减当前目录路径
        var curFilePath = ''
        var curFileObjBranch = {} // 获取当前文件父级对象分支

        for (var i = 0; i < pathArray.slice(0, pathArray.length - 1).length; i++) {
          if (curFilePath === '') {
            curFilePath = pathArray.slice(0, pathArray.length - 1)[i]
          } else {
            curFilePath = curFilePath + '/' + pathArray.slice(0, pathArray.length - 1)[i]
          }

          if (!this.$task.judgeIsNullObj(curFileObjBranch)) { // 初始时直接file_obj赋值
            curFileObjBranch = fileObj[pathArray.slice(0, pathArray.length - 1)[0]]
          } else {
            // 不是初始值在curFileObjBranch中取
            curFileObjBranch = curFileObjBranch[pathArray.slice(0, pathArray.length - 1)[i]]
          }
        }
        window.localStorage.curFileBranchPath = curFilePath

        window.localStorage.curFileObjBranch = JSON.stringify(curFileObjBranch)
        this.$router.push('/property/uploadreviewdetails')
        this.getBaseData()
      } else {
        window.localStorage.removeItem('curfileIndexDbIndexObj')
        window.localStorage.removeItem('curFileObjBranch')
        window.localStorage.removeItem('curFileBranchPath')
        window.localStorage.removeItem('curFileBranchHierarchy')
        this.$router.go(-1)
      }
    },
    selectedFile (el) {
      let li = document.getElementsByClassName('file_review_list')[0].children
      for (let i = 0, liL = li.length; i < liL; i++) {
        li[i].className = ''
      }
      el.currentTarget.className = 'on'
    },
    openfile (value, keys) {
      window.localStorage.curFileObjBranch = JSON.stringify(value) // 存储当前文件对象分支
      window.localStorage.curFileBranchHierarchy++ // 加层级-即当前目录层级
      var parentPath = window.localStorage.curFileBranchPath // 获取父级路径
      window.localStorage.curFileBranchPath = parentPath + '/' + keys // 当前目录路径
      var curfileIndexDbIndexObj = {} // 存放双击的文件在indexDB中的索引信息对象
      if (this.$task.getType(value) === 'obj') { // 判断是不是对象,是对象则为文件夹
        // 如果为文件夹则存入其对象分支,当前对象在文件对象树上的层级,并跳转至文件列表页面

        window.localStorage.zipfile_index = JSON.stringify(this.zipfile_index) // 存储文件在数组中的索引对象
        this.$router.push('/property/uploadreviewdetails')
        this.getBaseData()
      } else { // 不是对象则为文件
        // 如果为文件则存入其信息,跳转文件处理页面
        curfileIndexDbIndexObj = {index: this.zipfile_index[parentPath + '/' + keys], filename: keys}
        // 把文件索引信息存入localStorage
        window.localStorage.curfileIndexDbIndexObj = JSON.stringify(curfileIndexDbIndexObj)
        this.$router.push('/property/uploadreviewfile')
      }
    },
    fileTypeNameJudge (fileName) {
      if (fileName.indexOf('.') !== -1) {
        var sliptFileNameArr = fileName.split('.')
        if (sliptFileNameArr[sliptFileNameArr.length - 1].toLowerCase() === 'jpg' ||
            sliptFileNameArr[sliptFileNameArr.length - 1].toLowerCase() === 'png' ||
            sliptFileNameArr[sliptFileNameArr.length - 1].toLowerCase() === 'jpeg' ||
            sliptFileNameArr[sliptFileNameArr.length - 1].toLowerCase() === 'gif'
        ) {
          return { file_status: 0, file_type: 'photo' }
        } else if (sliptFileNameArr[sliptFileNameArr.length - 1].toLowerCase() === 'xls' ||
            sliptFileNameArr[sliptFileNameArr.length - 1].toLowerCase() === 'xlsx' ||
            sliptFileNameArr[sliptFileNameArr.length - 1].toLowerCase() === 'xlsm' ||
            sliptFileNameArr[sliptFileNameArr.length - 1].toLowerCase() === 'xltx' ||
            sliptFileNameArr[sliptFileNameArr.length - 1].toLowerCase() === 'xltm' ||
            sliptFileNameArr[sliptFileNameArr.length - 1].toLowerCase() === 'xlt'
        ) {
          return { file_status: 0, file_type: 'excel' }
        } else {
          return { file_status: 0, error_name: '无法识别此文件' }
        }
      } else {
        return { file_status: 1, file_type: 'dir' }
        // return { file_status: 1, error_name: '读取错误' }
      }
    },
    getBaseData () {
      this.zipfile_index = JSON.parse(window.localStorage.zipfile_index) // 存储文件在数组中的索引对象
      this.curFileObjBranch = JSON.parse(window.localStorage.curFileObjBranch) // 获取当前文件对象分支
    }
  }
}
</script>

代码说明: 先获取文件在数组中的索引对象及当前文件对象分支,然后渲染,双击文件时跟上面的类似,就是在返回上一级的时候麻烦些,得从文件对象树里面找到当前分支的位置,然后把当前分支的父级找到,再父级分支变为当前分支,减去目录层级以及相关信息的存储。

到了这里实战就结束了,完整的样子展示如图:




小结:

至此这个项目实战就结束了,总计奋战了好几天,这里想办法在github上把项目:VUEIndexDBOnlineZIP分享给大家,祝大家学习愉快。

提示:在最近几天我会慢慢附上VUE系列教程的其他后续篇幅,后面还有精彩敬请期待,请大家关注我的专题:web前端。如有意见可以进行评论,每一条评论我都会认真对待。

猜你喜欢

转载自blog.csdn.net/nongshuqiner/article/details/64922395