美文网首页
前端下载文件兼容IE

前端下载文件兼容IE

作者: tikeyc | 来源:发表于2022-06-06 17:38 被阅读0次
    <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>
    
    

    相关文章

      网友评论

          本文标题:前端下载文件兼容IE

          本文链接:https://www.haomeiwen.com/subject/mibjmrtx.html