关于(后端返回二进制文件流)输出Excel文件的导出、下载模板和上传操作?

1,985 阅读2分钟

前言

Excel格式在大家看来并不陌生,项目工作中经常会用到将某个表格中的数据,或者是后端传输的数据,作为一个Excel文件进行导出保存。接下来讲下如何通过'file-saver'依赖包实现Excel文件导出、下载模板和上传需求的。

需求如下:

需求是这里有一个员工列表数据需要通过点击右上方的'excel导入' 'excel导出' 按钮实现,并且发送导出的请求后端返回的是一个二进制文件流

Excel文件导入导出.jpg

接口文档.jpg

二进制文件流.jpg

根据接口文档分别封装好三个API:

// 导入员工(上传excel)
export const importFile = (data) => {
  return request({
    url: '/sys/user/import',
    method: 'POST',
    data        // 后端要data的值是'form-data'格式
  })
}


// 下载导入员工
export const importTemplate = () => {
  return request({
    url: '/sys/user/import/template',
    // 如果后端明确表示返回的是二进制文件流,这儿要通过下面代码告诉 axios
    responseType: 'blob'
  })
}


// 导出员工excel
export const exportEmployee = () => {
  return request({
    url: '/sys/user/export'
    // 如果后端明确表示返回的是二进制文件流,这儿要通过下面代码告诉 "xios responseType: 'blob'"
  })
}

导出excel按钮:

1.终端安装依赖包

npm i file-saver   //安装'file-saver'依赖包

2.设置响应拦截器

// 2.2 响应拦截器
request.interceptors.response.use(res => {
// 因为返回的是二进制,因此需要判断一下如果是二进制,直接返回res.data
  if (res.data instanceof Blob) return res.data 
  ...
}
<el-row class="opeate-tools" type="flex" justify="end">
  <el-button size="mini" @click="exportExcel">excel导出</el-button>    //绑定按钮的点击事件
</el-row>
    
<script>
  import { exportEmployee } from '@/api/employee'       //导入封装好的导出员工接口函数
  import { saveAs } from 'file-saver'           //按需从'file-saver'依赖包 导入saveAs储存文件
 
  methods: {
    async exportExcel() {
      // const r = await exportEmployee()                //通过点击事件调用导出excel接口api
      // console.log(r)
      saveAs(await exportEmployee(), '员工信息.excel')   //通过依赖包
    },
</script>

下载导入员工模板:

显示隐藏.jpg

<el-dialog width="500px" title="员工导入" :visible="showExcelDialog" @close="$emit('update:showExcelDialog', false)">
       <el-button type="text" @click="downloadTemplate">下载导入模板</el-button>
</el-dialog>

<script>
import { saveAs } from 'file-saver'               //按需从'file-saver'依赖包 导入saveAs储存文件
import { importTemplate } from '@/api/employee'   //导入封装好的下载导入员工模板接口api
export default {
  props: {
    showExcelDialog: {                            //接收父组件的弹窗传值
      type: Boolean,
      default: false
    }
  },
  methods: {
    async downloadTemplate() {                    //点击下载模板按钮
      saveAs(await importTemplate(), '下载模板.excel')    //调用下载excel模板请求,执行下载
    },
  }
}
</script>

模板和excel.jpg

导出员工excel:

上传显示隐藏.jpg

<el-dialog width="500px" title="员工导入" :visible="showExcelDialog" @close="$emit('update:showExcelDialog', false)">
   <input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="uploadchang">
     <span>将文件拖到此处或
         <el-button type="text" @click="uploadFiel">点击上传</el-button>
     </span>
</el-dialog>

<script>
import { saveAs } from 'file-saver'               //按需从'file-saver'依赖包 导入saveAs储存文件
import { importTemplate } from '@/api/employee'   //导入封装好的下载导入员工模板接口api
export default {
  props: {
    showExcelDialog: {                            //接收父组件的弹窗传值
      type: Boolean,
      default: false
    }
  },
  methods: {
    uploadFiel() {
//如何拿到到文件信息?
//点击普通的上传按钮的时候,找到'file dom',主动触发它的点击,监听原生'input file' 的 change事件,在change回调中就可以拿到文件信息
      this.$refs['excel-upload-input'].click()   //找到'file dom',主动触发它的点击,
    },
  async uploadchang(e) {
      const file = e.target.files[0] // 取[0]下标,第一个上传的文件
      if (file) {
        try {
          // 1.转换为formData格式
          const form = new FormData()
          // name是后端固定的'file',value值就是文件信息
          form.append('file', file)
          // 2.上传到后端
          await importFile(form)
          // 3.前端更新数据
          this.$emit('getDepartments')
          // 4.关闭弹窗
          this.$emit('update:showExcelDialog', false)
          // 5.成功提示信息
          this.$message.success('导入成功')
        } catch (e) {
          console.log(e)
        } finally {
          // 注意:需要把input file框中的 value文件清空,防止两次上传同一个文件,不触发@change事件
          this.$refs['excel-upload-input'].value = ''
        }
      }
    }
  }
  
}
</script>

导入成功.jpg

结尾

此文章主要针对后端返回的二进制文件流,同时需要输出的是Excel格式输出Excel文件的导出、下载模板和上传需求(仅供参考交流)。
注意点:两次上传同一个文件的时候,不会触发@chang事件,需要将'input file'框中的value值清空掉。