当前位置: 首页 > article >正文

导出文件,能够导出但是文件打不开

背景:

在项目开发中,对于列表的查询,而后会有导出功能,这里导出的是一个excell表格。实现了两种,1.导出的文件,命名是前端传输过去的;2.导出的文件,命名是根据后端返回的文件名获取的。

 //解码获取导出文件名

        const fileNames = res.headers['content-disposition']

        const fileName = decodeURIComponent(fileNames.match(/=(.*)$/)[1])

//能够导出但是打不开,导出接口的网络请求要带上responseType: 'blob',

     //导出文件【get】

    exportCrewInfoFile(params) {

        return request.Get("/data/ferryShip/download?", params, {

            headers: {

                "Content-Type": "application/json",

            },

            responseType: 'blob',

        });

    },

    //导出文件【post】

    exportWarningFile(params) {

        return request.Post("/data/warningRecord/download", params, {

            headers: {

                "Content-Type": "application/json",

            },

            responseType: 'blob',

        });

    },

前端界面:

前端请求接口,axios发起网络请求:

axios封装:

import axios from "axios";
import useShoreBasedStore from "@/store";
import qs from 'qs';
import router from "@/router/index.js";
import { ElMessageBox } from "element-plus";

let messageBoxVisible = false
export const BASEUrl = import.meta.env.VITE_USER_NODE_ENV === 'development' ? '/apiproxy/pa' : import.meta.env.VITE_API_URL + '/pa'
const request = axios.create({
    baseURL: BASEUrl,
    timeout: 3000 * 60,
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
});

/**
 * 请求拦截添加token
 * */
request.interceptors.request.use((config) => {
    const user = useShoreBasedStore();
    if (user.userInfo.token) {
        config.headers.Authorization = user.userInfo.token;
    }
    return config;
}, (error) => {
    return Promise.reject(error)
});

const showMsg = () => {
    if (!messageBoxVisible) {
        messageBoxVisible = true
        const user = useShoreBasedStore()
        ElMessageBox.confirm(
            '您的登录信息已过期,请重新登录!',
            '温馨提示',
            {
                confirmButtonText: '确认',
                cancelButtonText: '取消',
                type: 'warning'
            }
        ).then(() => {
            user.loginOut()
            router.push({ name: 'login' })
        }).catch(() => {
        }).finally(() => {
            messageBoxVisible = false
        })
    }
}

request.interceptors.response.use((response) => {
    const data = response.data
    if (data.status === 401 || data.code === 401) {
        showMsg()
    } else {
        return response
    }
}, (error) => {
    if (error.response.data.code === 401) {
        showMsg()
    } else {
        return Promise.reject(error)
    }
})

// 定义get方法
request.Get = function (url, params, config) {
    if (params) {
        return request.get(url + qs.stringify(params), config);
    }
    return request.get(url, config);
};

// 定义post方式
request.Post = function (url, params, config) {
    if (params) {
        return request.post(url, params, config);
    }
    return request.post(url, config);
};

export default request;

接口:

import request from "../utils/request.js";

const fileApi = {
    // 上传文件
    uploadFile(params) {
        return request.Post("/data/file/upload", params, {
            headers: {
                "Content-Type": "multipart/form-data",
            },
        });
    },
    // 删除文件
    deleteFile(params) {
        return request.Post("/data/file/delete", params, {
            headers: {
                "Content-Type": "application/json",
            },
        });
    },
    //导出文件【get】
    exportFerryPortFile(params) {
        return request.Get("/data/ferryPort/download?", params, {
            headers: {
                "Content-Type": "application/json",
            },
            responseType: 'blob',
        });
    },
    //导出文件【post】
    exportWarningFile(params) {
        return request.Post("/data/warningRecord/download", params, {
            headers: {
                "Content-Type": "application/json",
            },
            responseType: 'blob',
        });
    },
}
export default fileApi;

导出封装的方法: 

/**
 *
 * @param {*} fileContent 文件本体
 * @param {*} _fileName 自定义文件名
 */
export const exportFileUtil = (fileContent, _fileName) => {
  const content = fileContent;
  const blob = new Blob([content], {
    type: fileContent.type || "application/octet-stream; charset=utf-8",
  });
  const fileName = _fileName;
  if ("download" in document.createElement("a")) {
    //非IE下载
    const a = document.createElement("a"); //创建一个a标签
    a.download = fileName; //指定文件名称
    a.style.display = "none"; //页面隐藏
    a.href = URL.createObjectURL(blob); // href用于下载地址
    document.body.appendChild(a); //插到页面上
    a.click(); //通过点击触发
    URL.revokeObjectURL(a.href); //释放URL 对象
    document.body.removeChild(a); //删掉a标签
  } else {
    //IE10 + 下载
    navigator.msSaveBlob(blob, fileName);
  }
};
/**
 * 
 * @param {*} res 接口返回的文件流
 */
export const dowloadFileUrl = (res) => {
  const fileNames = res.headers['content-disposition']
  if (fileNames) {
      //解码
      const fileName = decodeURIComponent(fileNames.match(/=(.*)$/)[1])
      // 处理返回的文件流
      const content = res.data
      const blob = new Blob([content], {
          type: res.data.type||"application/vnd.ms-excel"
      });
      if ('download' in document.createElement('a')) {
          //非IE下载
          const a = document.createElement('a') //创建一个a标签
          a.download = fileName //指定文件名称
          a.style.display = 'none' //页面隐藏
          a.href = URL.createObjectURL(blob) // href用于下载地址
          document.body.appendChild(a) //插到页面上
          a.click() //通过点击触发
          URL.revokeObjectURL(a.href) //释放URL 对象
          document.body.removeChild(a) //删掉a标签
      } else {
          //IE10 + 下载
          navigator.msSaveBlob(blob, fileName)
      }
  }
}

使用导出的方法:

//只是举例,根据实际进行调整
const exportExcel = () => {
  const search = searchForm.value.submitData();
  const params = {
    ...search,
  };
  api.fileApi
    .exportCrewInfoFile(params)
    .then((res) => {
      if (res.status === 200) {
        exportFileUtil(res.data, "渡口管理导出文件.xlsx");
        dowloadFileUrl(res)
      }
    })
    .finally((err) => {
      console.log(err);
    });
};

写到这儿,就实现了导出功能。。。下面的是导出接口的详细解释: 

 

一、导出文件使用get请求

(1)、导出文件,get请求里面传参有数组等复杂数据结构

前端界面:

上图可以看见post查询接口可以返回4条数据,那么导出功能以同样的参数也应该导出4条数据的excell。

导出传参:

结果:

导出文件但是打不开,原因可能是:传参的问题;接口返回的数据有问题。 

能够导出,不能打开文件。

 经过排查,是前端请求有问题,如下图:

能够导出,并且能够打开的。get请求的响应体和请求体的结构。如下:请求传参带上,responseType: 'blob',【必须带上】

二、导出文件使用post请求 

前端界面:

导出传参:

总结:

导出功能,不管前端使用的是get或者post请求,都需要后端对接受到的传参进行识别,进而返回对应的响应体。 

前端请求一定要带上responseType: 'blob',


http://www.kler.cn/a/500693.html

相关文章:

  • [人工智能自学] Python包学习-pandas
  • 汇编学习笔记
  • 操作系统之磁盘
  • 【Ubuntu与Linux操作系统:一、Ubuntu安装与基本使用】
  • 【2024年华为OD机试】 (A卷,100分)- 租车骑绿岛(Java JS PythonC/C++)
  • unity 播放 序列帧图片 动画
  • stm32中断定义流程及应用
  • linux 读取txt文件做为文件路径
  • 如何在 IDEA 中配置 npm ?
  • springboot使用Easy Excel导出列表数据为Excel
  • 【C++习题】22.随机链表的复制
  • 【AJAX详解】
  • 1-1 电场基本概念
  • Kafka 会丢消息吗?
  • 【赵渝强老师】什么是NoSQL数据库?
  • Redis是单线程还是多线程?
  • 反向代理模块。
  • 通过LlaMA-Factory导出的模型部署到Ollama
  • MySQL的增删改查(基础)-下篇
  • 利用 Java 爬虫获取淘宝商品详情 API 接口
  • spark汇总
  • Springboot3.4整合jsp
  • 通信与网络安全之网络连接
  • 【pycharm发现找不到python打包工具,且无法下载】
  • nginx反向代理及负载均衡
  • EdgeOne安全专项实践:上传文件漏洞攻击详解与防范措施