下载文件--后端返回文件数据,前端怎么下载呢

问题:有个功能是将tabel数据导出,并且后端写了个接口,这个接口返回你要下载的excel文件数据了。前端请求接口就行,然后下载下来,但前端该怎么操作(发起请求呢)

/**
 * 导出文件
 * @param {string} url - 导出文件的 API 地址
 * @param {Object} data - 导出文件的请求参数
 */
export function exportFile(url, data) {
  const reqData = {
    ...data,
    ...initReqData(),//一些必要固定参数
  };

  axios({
    url,
    baseURL: import.meta.env.VITE_BASE_URL,
    data: reqData,
    responseType: 'blob',//设置为'blob',表示期望服务器响应的数据类型为二进制大对象(Blob),这对于下载文件特别有用。
    method: 'post',
  }).then(res => {
    if (res.data.type === 'application/json') {
      throw res;
    }
    const link = document.createElement('a');
    const blob = new Blob([res.data], { type: 'application/vnd.ms-excel' });
    link.style.display = 'none';
    link.href = URL.createObjectURL(blob);
    const contentDisposition = res.headers['content-disposition'];
    let needle = 'filename*=utf-8\'\'';
    let index = contentDisposition.indexOf(needle);
    if (index < 0) {
      needle = 'filename=';
      index = contentDisposition.indexOf(needle);
    }
    let fileName = contentDisposition.substring(index + needle.length);
    fileName = decodeURI(fileName);
    link.setAttribute('download', `${fileName}`);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    message.success('导出成功');
  }).catch(error => {
    try {
      const reader = new FileReader();
      reader.readAsText(error.data, 'utf-8');
      reader.onload = () => {
        const errData = JSON.parse(reader.result);
        message.error(errData.msg);
      };
    } catch (e) {
      message.error('导出错误,请联系管理员');
    }
  });
}

请求发送

  1. 请求配置
    • url:请求的URL,这里假设它已经在外部定义好了。
    • baseURL:通过import.meta.env.VITE_BASE_URL获取基础URL,这是Vite环境变量的一种用法,用于在开发、测试和生产环境中配置不同的基础URL。
    • datareqData,这是要发送到服务器的数据。
    • responseType:设置为'blob',表示期望服务器响应的数据类型为二进制大对象(Blob),这对于下载文件特别有用。
    • method'post',表示这是一个POST请求。
  2. 请求发送:使用axios发送配置好的请求。

响应处理

  1. 检查响应类型
    • 首先,检查响应的Content-Type。如果响应类型是'application/json',则抛出异常,因为预期是下载文件而不是接收JSON数据。
  2. 处理文件下载
    • 创建一个Blob对象,将响应数据(res.data)作为其内容,并设置MIME类型为'application/vnd.ms-excel',这是Excel文件的MIME类型。
    • 创建一个隐藏的<a>标签,设置其href属性为Blob对象的URL(通过URL.createObjectURL(blob)生成),并设置download属性为文件名(从Content-Disposition响应头中提取)。
    • <a>标签添加到文档中,模拟点击以触发下载,然后立即从文档中移除该标签。
    • 显示“导出成功”的消息。

错误处理

  1. 捕获异常
    • 如果在下载过程中发生错误(如服务器返回JSON格式的错误信息),则尝试读取错误响应的data部分作为文本。
    • 使用FileReader读取响应数据,并将其解析为JSON对象。
    • 如果解析成功,则显示错误消息(errData.msg)。
    • 如果在读取或解析过程中发生任何异常,则显示一般的错误消息“导出错误,请联系管理员”。

部分代码解析:

主要用于从HTTP响应的Content-Disposition头部中提取文件名,并设置给一个<a>标签的download属性,以便在点击该链接时以下载的形式保存文件。下面是对这几部分代码的详细讲解:

1. 提取Content-Disposition头部

const contentDisposition = res.headers['content-disposition'];

这行代码从HTTP响应的头部信息中获取Content-Disposition字段的值。这个字段通常用于指示响应的内容应该如何显示,对于文件下载来说,它还可能包含文件名。

2. 处理文件名编码

HTTP标准允许Content-Disposition中的文件名使用不同的编码方式,特别是当文件名包含非ASCII字符时。这里,代码首先尝试找到使用RFC 5987编码的文件名(即filename*=utf-8''这种格式),如果没有找到(indexOf返回-1),则回退到较旧的filename=格式。

let needle = 'filename*=utf-8\'\'';
let index = contentDisposition.indexOf(needle);
if (index < 0) {
needle = 'filename=';
index = contentDisposition.indexOf(needle);
}
  • needle变量用于存储要搜索的字符串(即文件名前的标识符)。
  • indexOf方法用于查找needlecontentDisposition字符串中的位置。
  • 如果找不到使用RFC 5987编码的文件名(index < 0),则更改needlefilename=并再次搜索。

3. 提取文件名

let fileName = contentDisposition.substring(index + needle.length);

一旦找到了文件名的起始位置(index + needle.length),就使用substring方法从该位置开始提取剩余的字符串作为文件名。这包括了文件名本身以及可能存在的任何引号(如果使用的是filename=格式,则文件名可能会被引号包围)。

4. 解码文件名

fileName = decodeURI(fileName);

由于文件名可能是经过URI编码的(特别是当包含特殊字符或空格时),因此使用decodeURI函数对其进行解码,以确保文件名在下载时正确显示。

5. 设置下载链接

link.setAttribute('download', `${fileName}`);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
  • 使用setAttribute方法将解码后的文件名设置为<a>标签的download属性。这告诉浏览器,当用户点击该链接时,应以下载的形式保存内容,并使用指定的文件名。
  • <a>标签添加到文档的body中,以便可以触发其点击事件。
  • 调用click方法模拟点击事件,触发下载。
  • 下载完成后,立即从文档中移除<a>标签,以清理DOM。

这样,当用户通过这段代码触发下载时,浏览器会根据Content-Disposition头部中的信息(特别是文件名)来保存文件。

 

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue中使用pdfjs-dist插件时,你需要将后端返回的PDF文件路径传递给前端,以便正确加载和显示PDF文件。下面是一个示例,展示如何在后端返回正确的PDF文件路径给前端: 1. 后端应该提供一个API接口,用于获取PDF文件的路径。你可以使用任何后端技术栈来实现这个接口,例如Node.js、Java、Python等。 2. 在后端代码中,根据你的业务逻辑,将PDF文件路径作为响应返回前端。这个路径可以是相对路径或绝对路径,取决于你的项目设置。 3. 前端通过调用后端提供的API接口来获取PDF文件路径。可以使用Vue的HTTP请求库(如axios)来发送请求,获取后端返回数据。 4. 在前端接收到后端返回的PDF文件路径后,将路径传递给Vue组件中的loadPDF方法。你可以通过props、data或其他方式将路径传递给Vue组件。 下面是一个简单的示例代码片段,展示了如何在Vue中使用axios库来获取后端返回的PDF文件路径: ```javascript import axios from 'axios'; export default { data() { return { pdfPath: '', }; }, methods: { async fetchPDFPath() { try { const response = await axios.get('/api/get-pdf-path'); this.pdfPath = response.data.path; this.loadPDF(); } catch (error) { console.error('Failed to fetch PDF path:', error); } }, loadPDF() { // 使用this.pdfPath加载和显示PDF文件 // ... }, }, mounted() { this.fetchPDFPath(); }, }; ``` 在上述示例中,假设后端提供了一个`/api/get-pdf-path`的API接口来获取PDF文件路径。`fetchPDFPath`方法使用axios库来发送GET请求,获取后端返回数据,并将PDF文件路径赋值给`this.pdfPath`。然后,调用`loadPDF`方法来加载和显示PDF文件。 请根据你的实际情况和后端实现来进行适当的修改。确保后端正确返回PDF文件路径,并在前端将其传递给Vue组件中的加载方法。 希望这可以帮助你解决问题!如果你还有其他疑问,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值