• 前端文件流下载填坑之旅


    在一个地方连续踩了2次坑,对于我这种记性不好的来说,只能博客赶紧记录一下了,文件流下载的适用场景是: 前端页面点击导出按钮后调取后端接口,接口返回数据,然后通过下载函数处理,下载保存到本地,下面分享下都遇到哪些坑:


    一. 接口需配置 responseType

    坑一: responseType配置项必须传,一般只在前端配置,后端不做处理,此处的type就是调用该接口时传进来的文件转换类型,意思是前端接收到流后以什么类型转换,然后可供下载

    1. // xx 导出
    2. export function handleExport(params, type) {
    3. return request({
    4. url: `xxxxx/export`,
    5. method: 'post',
    6. data: params,
    7. responseType: type,
    8. })
    9. }

    二. 调用接口并传参

    下图中,params是自己接口的正常传参,‘blob’就是上面接口传的type类型,因为我们项目都是xls表格类型结尾的,所以我设置的blob,为什么可以自行百度,downloadFile即下载函数,下面会介绍

    1. /**
    2. * 导出
    3. */
    4. handleExport() {
    5. this.$confirm('确定要导出所有线下订单吗?', '导出提示', {
    6. confirmButtonText: '确定',
    7. cancelButtonText: '取消',
    8. }).then(async () => {
    9. this.exportLoading = true
    10. const exportRes = await handleExport(parmas, 'blob').catch((err) => {
    11. this.exportLoading = false
    12. })
    13. this.exportLoading = false
    14. downloadFile(exportRes, '线下订单明细')
    15. })
    16. },

    坑二: 这里需要注意的是,因为现在前端大部分项目都使用axios拦截器,而文件流接口回来的数据可能与其他接口不统一,导致被拦截器拦截,那拿到的数据肯定不对,怎么转换都是错的啦,我就在此处绊住半天,下面是我自己项目中的处理方式,你们可以根据自己项目的数据处理

    1. /**
    2. * @description axios响应拦截器
    3. */
    4. instance.interceptors.response.use(
    5. (response) => {
    6. console.log(response) // 此处可以打印先看下返回的数据格式,方便下面处理
    7. const { config, data, status } = response
    8. const exportUrlList = [`${shopUrl}/orderItem/export`]
    9. if (exportUrlList.includes(config.url)) {
    10. // 导出接口,返回数据格式与其他不统一,需特殊处理
    11. if (status === 200) {
    12. return data
    13. } else {
    14. Vue.prototype.$baseNotify('导出失败!', '提示', 'error')
    15. return Promise.reject({
    16. noShow: true,
    17. message: '导出失败!',
    18. })
    19. }
    20. } else {
    21. return handleData(response) // 这是其他的统一处理的函数
    22. }
    23. },
    24. (error) => {
    25. const { response } = error
    26. if (response === undefined) {
    27. Vue.prototype.$baseMessage('未可知错误,大部分是由于后端不支持跨域CORS或无效配置引起', 'error')
    28. return {}
    29. } else return handleData(response)
    30. }
    31. )

     

    三. 下载,保存到本地

    成功拿到返回数据后,就是进行下载 ,下图就是下载的处理过程,可以拿去用,new Blob 还可以传入其他参数,此处我没有传,如果特殊处理可以自己传,自行了解new Blob的用法,此处用的moment可以npm下载,当然前端项目基本都会用到

    1. /**
    2. * @description 下载文件流
    3. * @param response 文件流
    4. * @param fileName 文件名称
    5. */
    6. export function downloadFile(response, fileName) {
    7. const blob = new Blob([response])
    8. const a = document.createElement('a')
    9. const URL = window.URL || window.webkitURL // 兼容webkix浏览器,处理webkit浏览器中href自动添加blob前缀,默认在浏览器打开而不是下载
    10. a.href = URL.createObjectURL(blob) // 根据解析后的blob对象创建URL 对象
    11. a.download = `${fileName}-` + moment().format('YYYYMMDDHHmmss') + '.xls'
    12. //此写法兼容可火狐浏览器
    13. document.body.appendChild(a)
    14. let evt = document.createEvent('MouseEvents')
    15. evt.initEvent('click', false, false)
    16. a.dispatchEvent(evt)
    17. document.body.removeChild(a)
    18. }

     四. 文件保存后,验证是否可以正常打开

    坑三:保存后,如果能正常打开且显示数据正常,请忽略下面的问题。如果打开发现还是会提示文件格式不正确,什么鬼?各种查阅后,发现是mock请求导致的,mock请求将request改为了MockXMLHttpRequest(如下图所示),data也是乱码

    解决方法: 屏蔽掉mock引入,再调接口,返回数据如下图所示,data返回时Blob格式,就ok了 ,此时下载保存到桌面就没问题啦!


    当然以上只是我遇到的问题,如果情况不符合你的预期,那你再去查查别的相关资料,希望能帮到你

  • 相关阅读:
    Redis - 利用lua脚本控制密码错误次数超限,锁定账号
    火星探测器背后的人工智能:从原理到实战的强化学习
    利用EasyDL制作一个简单的图片识别小项目
    大厂Java岗面试原题复盘,双非2年经验成功内推进入阿里
    Linux下安装和使用MySQL的详细教程
    【Git】git 分支或指定文件回退到指定版本
    23云计算全国职业技能大赛容器云-容器编排
    2022CCPC威海补题:A C E G J
    笔记本电脑wifi怎么连接
    2 Java并发原理精讲课程学习笔记
  • 原文地址:https://blog.csdn.net/weixin_41326021/article/details/125527072