Vue项目中实现预览功能,以及下载到本地

542 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

今天要实现的需求有两个,一个是根据后端返回的url可以在页面中实现预览,不是下载到本地哦,第二个需求就是根据后端返回的url,直接下载到本地,话不多说,直接上代码。

预览

1、html布局结构

   <el-button @click='goPreview'>点击预览word文件</el-button>
   <div class='docWrap'>
      <!-- 预览文件的地方(用于渲染) -->
      <div ref='file'></div>
    </div>

预览文件的样式自己根据需求调整

2、插件下载

 npm i docx-preview
 npm i axios

3、导入插件

// 引入axios用来发请求
import axios from 'axios'
// 引入docx-preview插件
const docx = require('docx-preview')

2、js代码实现

 // 预览
    goPreview () {
      axios({
        method: 'get',
        responseType: 'blob', // 因为是流文件,所以要指定blob类型
        url: 'http://101.91.204.115:8389/default/2022/06/02/1/1654142037781/预览文档.docx' // 自己的服务器,提供的一个word下载文件接口
      }).then(({ data }) => {
        console.log(data) // 后端返回的是流文件
        docx.renderAsync(data, this.$refs.file) // 渲染到页面
      })
    },

下载到本地

1、html布局结构

 <el-button @click='goPreview'>点击预览word文件</el-button>

2、js代码实现

// 后端返回的是blob流文件
    downLoad () {
      axios({
        method: 'get',
        responseType: 'blob', // 因为是流文件,所以要指定blob类型
        url: 'http://101.91.204.115:8389/default/2022/06/02/1/1654142037781/下载文件.docx' // 自己的服务器,提供的一个word下载文件接口
      }).then(({ data }) => {
        console.log(data) // 后端返回的是blob流文件
        const blob = new Blob([data]) // 把得到的结果用流对象转一下
        const a = document.createElement('a') // 创建一个<a></a>标签
        a.href = URL.createObjectURL(blob) // 将流文件写入a标签的href属性值
        a.download = '文件名.docx' // 设置文件名
        a.style.display = 'none' // 障眼法藏起来a标签
        document.body.appendChild(a) // 将a标签追加到文档对象中
        a.click() // 模拟点击了a标签,会触发a标签的href的读取,浏览器就会自动下载了
        a.remove() // 一次性的,用完就删除a标签
      })
    },
// 后端返回的是ArrayBuffer二进制文件流文件,要先转成blob
    downLoad2 () {
      axios({
        method: 'get',
        responseType: 'arraybuffer', // 指定arraybuffer二进制文件流
        url: 'http://101.91.204.115:8389/default/2022/06/02/1/1654142037781/下载文件.docx' // 自己的服务器,提供的一个word下载文件接口
      }).then(({ res }) => {
        console.log(res) // 后端返回的是arraybuffer二进制文件流
        if (!res) {
          this.$message.error('文件下载失败!')
          return false
        }
        // 这里res是返回的是arraybuffer二进制文件流,将二进制文件流转为blob
        const blob = new Blob([res], {
          type: 'application/octet-stream', // 匹配任意文件类型:type : "application/octet-stream"
          endings: 'transparent'
        })
        // 设置文件名
        // let contentDisposition = res.headers['content-disposition'] // 从Response Headers中获取content-disposition的值, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;
        // const patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*') // 设置正则表达式匹配格式
        // let patt = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; // 设置正则表达式匹配格式
        // let result = patt.exec(contentDisposition) // 通过正则表达式提取“filename=” 后的值

        const filename = '文件名.docx' // 提取文件名

        // 兼容IE,window.navigator.msSaveBlob:以本地方式保存文件
        if (typeof window.navigator.msSaveBlob !== 'undefined') {
          window.navigator.msSaveBlob(blob, decodeURI(filename))
        } else {
          const blobURL = window.URL.createObjectURL(blob) // 把blob转化为一个Blob URL
          const aLink = document.createElement('a') // 创建a标签,用于跳转至下载链接
          aLink.href = blobURL // 设置a标签href值
          aLink.setAttribute('download', filename) // 设置下载文件名称

          // if (res.config.params.fileType == undefined || res.config.params.fileType == '' || res.config.params.fileType == null) {
          //  aLink.setAttribute('download', res.config.params.fileName); // 设置下载文件名称
          // } else {
          //  aLink.setAttribute('download', res.config.params.fileName + '.' + res.config.params.fileType); // 设置下载文件名称
          // }

          // 兼容:某些浏览器不支持HTML5的download属性
          if (typeof aLink.download === 'undefined') {
            aLink.setAttribute('target', '_blank')
          }
          aLink.style.display = 'none' // 隐藏a标签
          document.body.appendChild(aLink) // a标签插入到body中
          aLink.click() // 模拟a标签点击事件 使其下载
          document.body.removeChild(aLink) // 移除a标签
          window.URL.revokeObjectURL(blob) // 释放掉blob对象
        }
      })
    }

cv就能实现功能你还在等什么!