前端下载文件兼容IE

2022-06-06  本文已影响0人  tikeyc
<template>
  <a
    v-if="method === 'post' || outOfService"
    :class="aClassName"
    @click="click"
  >
    <div v-if="$scopedSlots.exportType">
      <slot name="exportType" v-bind="{ handleSubmit }" />
    </div>
    <slot v-else><a-button>{{ btnText }}</a-button></slot>
    <div v-if="userFormData" v-show="false">
      <iframe :id="`__hidden_iframe_${id}__`" src="about:blank" :title="`__hidden_iframe_${id}__`" />
      <form ref="handleRefForm" :action="hrefValue" :method="method" :target="`__hidden_iframe_${id}__`">
        <input
          v-for="key in Object.keys(params)"
          :key="key"
          type="hidden"
          :name="key"
          :value="params[key]"
        >
      </form>
    </div>
  </a>
  <a v-else :href="hrefValue" :class="aClassName">
    <slot><a-button>{{ btnText }}</a-button></slot>
  </a>
</template>

<script>
import { stringify } from 'querystring'
import { axios } from '@/utils/request3'

const urlPrix = ''

export default {
  props: {
    // 是否使用form表单形式下载
    userFormData: {
      type: Boolean,
      default: false
    },
    // 请求方式
    method: {
      type: String,
      default: 'post'
    },
    // 请求地址
    href: {
      type: String,
      required: true,
      default: null
    },
    // 是否完整Url
    isCompleteUrl: {
      type: Boolean,
      default: false
    },
    // 参数
    params: {
      type: Object,
      default: () => ({})
    },
    // 样式
    aClassName: {
      type: String,
      default: ''
    },
    // 文件名的前缀
    fileNamePrix: {
      type: String,
      default: ''
    },
    // 导出按钮文字
    btnText: {
      type: String,
      default: '导出Excel'
    },
    // 是否停用, 点击将提示 - 正在开发中,敬请期待
    outOfService: {
      type: Boolean,
      default: false
    }
  },
  data() {
    const id = String(Math.random()).substring(2)
    return {
      id
    }
  },
  computed: {
    hrefValue() {
      const { method, href, params } = this
      if (this.isCompleteUrl) return href
      return method === 'post' ? `${urlPrix}${href}` : `${urlPrix}${href}?${stringify(params)}`
    }
  },
  methods: {
    click() {
      if (this.outOfService) {
        return this.$message.info(this.$t('msg.underDevelopment'))
      }
      if (!this.$scopedSlots.exportType) {
        this.handleSubmit()
      }
    },
    handleSubmit(otherParams) {
      if (this.userFormData) {
        this.$refs.handleRefForm.submit()
      } else {
        this.axiosMethodDownload(otherParams)
      }
    },
    async axiosMethodDownload(otherParams) {
      try {
        const { method, href, params } = this
        const url = this.isCompleteUrl ? href : urlPrix + href
        const res = await axios({
          url,
          method,
          data: { ...params, ...otherParams },
          responseType: 'arraybuffer' // blob(blob超过3M的文件无法下载)
        })
        if (res && res.data && (res.data instanceof Blob || res.data instanceof ArrayBuffer)) {
          const { data, headers } = res
          this.exportExcel(headers, data)
        }
      } catch (error) {
        console.error(error)
      }
    },
    exportExcel(headers = {}, response) {
      const contentDisposition = headers['content-disposition']
      const contentType = headers['content-type']
      let fileName = 'unknown'
      if (contentDisposition) {
        fileName = window.decodeURIComponent(headers.filename || headers['content-disposition'].split('=')[1].split('?')[0])
      }
      if (this.fileNamePrix) {
        fileName = `${this.fileNamePrix}-${fileName}`
      }
      const blob = new Blob([response], { type: contentType })
      this.downFile(blob, fileName)
    },
    downFile(blob, fileName) {
      // 非IE下载
      if ('download' in document.createElement('a')) {
        const link = document.createElement('a')
        link.href = window.URL.createObjectURL(blob) // 创建下载的链接
        link.download = fileName // 下载后文件名
        link.style.display = 'none'
        document.body.appendChild(link)
        link.click() // 点击下载
        window.URL.revokeObjectURL(link.href) // 释放掉blob对象
        document.body.removeChild(link) // 下载完成移除元素
      } else {
        // IE10+下载
        window.navigator.msSaveBlob(blob, fileName)
      }
    }
  }
}
</script>

<style lang="scss" scoped>

</style>

上一篇 下一篇

猜你喜欢

热点阅读