 闽公网安备 35020302035485号
                
                闽公网安备 35020302035485号
                首先,因为前端代码都是一样的,然后就需要对比他们请求的接口了,对比之后发现两个东西,一个返回的数据,上面的第一种中文是乱码的,然后后面两种都是正常的,再一个就是返回数据里的Response Headers中的Content-Type字段是不一样的,
第一个的Content-Type: application/octet-stream,
第二个和第三个都是Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,类似这种的,然后去查发现第二个和第三个都不是标准的Content-Type,后来才知道是自定义的一个告诉excel客户端,这是一个特殊文件。当然上面都是我的怀疑,怎么能知道真的就是接口返回的Content-Type的问题呢,你说直接找后端,后端不认说第一种不就可以用吗,你都是同一个代码下载的,怼的你都没话说,你还得自己回来找原因,那么不如直接先把原因找到。
const express = require('express');
const cors = require('cors');
const app = express();
// 配置CORS,允许跨域请求
app.use(cors());
app.get('/api/csv-data', (req, res) => {
    res.setHeader('Content-Type','text/csv')
    const data = '数据1,数据2,数据3'
    res.end(data)
});
const port = 3001;
// 堆代码 duidaima.com
// 启动服务
app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
});
启动起来我们的Node接口就写好了,我们就能前端调用下载测试了,前端页面代码如下:import axios from 'axios';
function App() {
  const downloadFile = (content, filename) => {
    // 创建一个 Blob 对象
    const blob = new Blob([content], { type: 'application/octet-stream' });
  
    // 创建一个 a 标签
    const link = document.createElement('a');
  
    // 设置 href 为 Blob 对象
    link.href = URL.createObjectURL(blob);
  
    // 设置下载的文件名
    link.download = filename;
  
    // 将 a 标签添加到 DOM
    document.body.appendChild(link);
  
    // 触发下载
    link.click();
  
    // 从 DOM 移除 a 标签
    document.body.removeChild(link);
    // 释放 Blob URL
    URL.revokeObjectURL(link.href);
  }
  const csvDownLoad = () => {
    axios.get(' http://localhost:3001/api/csv-data') 
    .then(response => {
      downloadFile(response.data,'测试CSV下载.csv')
    }).catch(error => {
      console.log(error);
    });
  }
  return <button onClick = {csvDownLoad}>下载CSV文件</button>;
}
export default App;
结果下载下来发现文件格式是对的,真的是csv文件,但是内容乱码了,咱也不知道这是啥字:
const express = require('express');
const cors = require('cors');
const app = express();
const iconv = require('iconv-lite');
// 配置CORS,允许跨域请求
app.use(cors());
// 读取CSV文件的接口
app.get('/api/csv-data', (req, res) => {
    res.setHeader('Content-Type', 'text/csv; charset=GBK');
    const data = '数据1,数据2,数据3';
    const gbkBuffer = iconv.encode(data, 'GBK');
    res.end(gbkBuffer);
});
const port = 3001;
// 启动服务
app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
});
然后我们继续使用前面的前端代码进行下载,你会发现下载下来的文件打开依然是乱码,这是为什么呢,我们的数据已经采用GBK编码了,为什么打开还是乱码呢。此时我就在想是不是前端代码下载有问题,看了一下前端下载的代码,发现axios获取到的响应数据是作为一个UTF-8字符串处理的,而不是原始的字节流。
	
因此,当你将其传递给Blob对象并下载时,它是以UTF-8编码的。也就是说前端下载的时候还是以UTF-8编码的,这是不行的,所以还是得以后端接口给的原来得编码格式进行编码,这样才不会乱码。为了解决这个问题,我们就需要告诉axios将响应数据作为原始的字节流(ArrayBuffer)处理,而不是将其作为UTF-8字符串处理。可以通过设置responseType为'arraybuffer'来实现这一点。这样,当数据从服务器返回时,它将保持其原始的GBK编码。
import axios from 'axios';
function App() {
  const downloadFile = (content, filename) => {
    // 创建一个 Blob 对象
    const blob = new Blob([content], { type: 'application/octet-stream' });
  
    // 创建一个 a 标签
    const link = document.createElement('a');
  
    // 设置 href 为 Blob 对象
    link.href = URL.createObjectURL(blob);
  
    // 设置下载的文件名
    link.download = filename;
  
    // 将 a 标签添加到 DOM
    document.body.appendChild(link);
  
    // 触发下载
    link.click();
  
    // 从 DOM 移除 a 标签
    document.body.removeChild(link);
    // 释放 Blob URL
    URL.revokeObjectURL(link.href);
  }
  const csvDownLoad = () => {
    axios.get(' http://localhost:3001/api/csv-data',{
      responseType: 'arraybuffer'
    }).then(response => {
      downloadFile(response.data,'测试CSV下载.csv')
    }).catch(error => {
      console.log(error);
    });
  }
  return <button onClick = {csvDownLoad}>下载CSV文件</button>;
}
export default App;
