vue-下载后端返回的文件流(post),上传,请求前置过滤器,响应数据拦截并做通用处理

vue-下载后端返回的文件流(post)

vue

<script>
import axios from 'axios'
import {MessageBox, Message} from 'element-ui'
import {Loading} from 'element-ui'

const http = axios.create({
  // baseURL: process.env.VUE_APP_BASE_API,
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 60000,
  withCredentials: true
})

export default {
    methods:{
     /**
     * 下载 url:后台地址 data:需要导出的数据 fileName:文件名
     * @param url 
     * @param data
     */
    download(url, data, fileName) {
      return new Promise((resolve, reject) => {
        // 打开
        const loading = Loading.service({
          text: '正在下载数据...',
          background: 'rgba(0, 0, 0, 0.7)'
        })
        http.request({
          url: url,
          method: 'post',
          data: data,
          timeout: 1200000,
          responseType: 'arraybuffer'
        })
            .then(res => {
              loading.close()
              // 文件下载
              const blob = new Blob([res.data], {
                type: 'application'
              })
              // 获得文件名称
              let link = document.createElement('a')
              link.download = fileName
              link.style.display = 'none'
              link.href = URL.createObjectURL(blob)
              document.body.appendChild(link)
              link.setAttribute('download', fileName + '.xls')
              link.click()
              URL.revokeObjectURL(link.href);
              document.body.removeChild(link);
              link = null
              Message.success('导出成功!')
            })
            .catch(err => {
              loading.close()
              reject(err)
            })
      })
    },
    }
}
</script>

django

  def export(self, request):
        ...... 获取数据根据实际情况获取
        # 假设数据是这样的
        ret = [[1, 'tom', 2], [2, 'jerry', 1]]
        import pandas as pd
        df = pd.DataFrame(ret, columns=['id', 'name', 'age'])
        # 利用pandas将数据存入excel文件中
        from io import BytesIO
        bio = BytesIO()
        writer = pd.ExcelWriter(bio, engine='xlsxwriter')  # 注意安装这个包 pip install xlsxwriter
        df.to_excel(writer, sheet_name='Sheet1')
        writer.save()
        bio.seek(0)
        # bio.read() 不要read出来,否则seek就到文件最后了,导致下载的是空文件
        # 至此,数据已写入bio中
        from django.http import FileResponse
        response = FileResponse(bio)
        response['Content-Type'] = 'application/octet-stream'
        response['Content-Disposition'] = 'attachment;filename="mm.xlsx"'
        return response

上传文件

vue

<script>
import axios from 'axios'
import {MessageBox, Message} from 'element-ui'
import {Loading} from 'element-ui'

const http = axios.create({
  // baseURL: process.env.VUE_APP_BASE_API,
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 60000,
  withCredentials: true
})

methods:{
    /**
     * 上传
     * @param url
     * @param data
     */
      upload (url, file, data) {
      const formData = new FormData()
      formData.append('file', file)

      // 附加数据
      if (data) {
        Object.keys(data).forEach(key => {
          formData.append(key, data[key])
        })
      }

      return new Promise((resolve, reject) => {
        // 打开
        const loading = Loading.service({
          text: '正在上传数据...',
          background: 'rgba(0, 0, 0, 0.7)'
        })

        http
          .request({
            url: url,
            method: 'post',
            data: formData,
            timeout: 1200000
          })
          .then(response => {
            console.log(response)
            loading.close()
            resolve(response)
          })
          .catch(err => {
            loading.close()
            reject(err)
          })
      })
    }
}
</script>

汇总

import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import { Loading } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'

// 请求实例
const http = axios.create({
  // baseURL: process.env.VUE_APP_BASE_API,
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 60000,
  withCredentials: true
})

// 请求前置过滤器
http.interceptors.request.use(
  config => {
    if (store.getters.token) {
      config.headers['token'] = getToken()
    }
    return config
  },
  error => {
    console.log(error)
    return Promise.reject(error)
  }
)

// 响应数据拦截并做通用处理
http.interceptors.response.use(
  response => {
    const res = response.data

    // 下载文件直接返回
    if (res.type === 'application/octet-stream') {
      return response
    }

    if (res.type === 'application/vnd.ms-excel') {
      return response
    }

    // 0为正确响应码
    // if (res.code !== 0 ) {
    //   Message({
    //     message: res.msg || 'Error',
    //     type: 'error',
    //     duration: 5 * 1000
    //   })
    //
    //   // 登录超时响应码
    if (res.code != 200 && res.message == '暂未登录或token已经过期') {
      // to re-login
      MessageBox.confirm('登录超时,请重新登录!', '登录提示', {
        confirmButtonText: '重新登录',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        store.dispatch('user/resetToken').then(() => {
          location.reload()
        })
      })
    } else {
      return res
    }
  },
  error => {
    console.log('err' + error)
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

/**
 * 上传
 * @param url
 * @param data
 */
export function upload (url, file, data) {
  const formData = new FormData()
  formData.append('file', file)

  // 附加数据
  if (data) {
    Object.keys(data).forEach(key => {
      formData.append(key, data[key])
    })
  }

  return new Promise((resolve, reject) => {
    // 打开
    const loading = Loading.service({
      text: '正在上传数据...',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    http
      .request({
        url: url,
        method: 'post',
        data: formData,
        timeout: 1200000
      })
      .then(response => {
        console.log(response)
        loading.close()
        resolve(response)
      })
      .catch(err => {
        loading.close()
        reject(err)
      })
  })
}

/**
 * 下载
 * @param url
 * @param data
 */
export function download (url, data, fileName) {
  return new Promise((resolve, reject) => {
    // 打开
    const loading = Loading.service({
      text: '正在下载数据...',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    http
      .request({
        url: url,
        method: 'post',
        data: data,
        timeout: 1200000,
        responseType: 'arraybuffer'
      })
      .then(res => {
        loading.close()

        // 文件下载
        const blob = new Blob([res], {
          type: 'application'
        })

        // 获得文件名称
        let link = document.createElement('a')
        link.href = URL.createObjectURL(blob)
        link.setAttribute('download', fileName)
        link.click()
        link = null
        Message.success('导出成功!')
      })
      .catch(err => {
        loading.close()
        reject(err)
      })
  })
}

/**
 * 封装post请求
 * @param url
 * @param data
 * @returns {Promise}
 */
export function post (url, data = {}) {
  return new Promise((resolve, reject) => {
    http.post(url, data).then(
      response => {
        resolve(response)
      },
      err => {
        reject(err)
      }
    )
  })
}

export default http
posted @ 2022-10-13 14:20  春游去动物园  阅读(1682)  评论(0编辑  收藏  举报