You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React.js通过GET请求下载PDF时遭遇CORS错误,寻求技术指导

解决React前端通过GET请求下载PDF的CORS及实现问题

先帮你梳理下当前代码里的几个关键问题,咱们一步步来修复:

1. 前端Fetch参数错误:Mode位置写错了

你现在把{mode: 'no-cors'}作为fetch的第三个参数了,但fetch的语法是fetch(url, options),mode必须放在第二个options对象里。而且用no-cors模式的话,你根本无法读取响应的blob内容——这种模式下浏览器会返回一个"opaque"(不透明)响应,无法访问任何响应属性,这也是你后续res.blob()报错的核心原因之一。

修正后的前端fetch调用(后面会推荐更简单的方案):

viewHandler = async (fileID) => { 
  fetch(`http://localhost:8000/download/${fileID}`, { 
    method: "GET", 
    headers: { 
      'Authorization': token ? `Bearer ${token}` : '', 
      // 这里不需要设置Content-Type,GET请求不需要发送内容类型头,这个字段是给请求体用的
    }
  }) 
  .then(res => {
    if (!res.ok) throw new Error('请求失败,请检查文件路径或权限');
    return res.blob();
  })
  .then(response => { 
    const file = new Blob([response], { type: "application/pdf" }); 
    const fileURL = URL.createObjectURL(file); 
    // 用a标签触发下载比window.open更稳妥,避免被浏览器拦截
    const a = document.createElement('a');
    a.href = fileURL;
    a.download = 'sample.pdf'; // 这里可以改成后端返回的文件名,或者自定义
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(fileURL); // 及时释放内存,避免内存泄漏
  }) 
  .catch(error => { 
    console.log(error); 
  }); 
};

2. 后端CORS配置冲突

你同时使用了app.use(cors())和自己手动编写的CORS中间件,这会导致响应头重复设置,反而可能引发CORS校验失败。建议保留其中一种配置即可,推荐直接使用cors包,配置更稳定可靠:

var app=express(); 
const cors = require('cors');
// 只保留cors中间件,移除你手动写的那个
app.use(cors({
  origin: 'http://localhost:3000', // 明确指定前端地址,比通配符*更安全
  methods: ['OPTIONS','GET','POST','PUT','PATCH','DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));
app.use(express.json()); 
app.use(express.urlencoded({extended:true})); 

// 移除你手动编写的CORS中间件代码

3. 后端控制器的参数读取错误

你写的req.param.fileId是语法错误,正确的写法是req.params.fileId(注意是复数params):

getFile(req,res){ 
  let fileId = req.params.fileId; // 修正参数读取方式
  // 重要:一定要校验fileId的路径安全性,防止路径遍历攻击(比如禁止../这类路径)
  const filePath = fileId; // 这里可以根据实际情况拼接根路径,比如`./files/${fileId}`
  // 先检查文件是否存在,避免报错
  if (!fs.existsSync(filePath)) {
    return res.status(404).send('文件不存在');
  }
  const src = fs.createReadStream(filePath); 
  res.writeHead(200, { 
    'Content-Type': 'application/pdf', 
    'Content-Disposition': 'attachment; filename=sample.pdf', 
    'Content-Transfer-Encoding': 'Binary' 
  }); 
  src.pipe(res); 
}

4. 更简单的PDF下载方案(强烈推荐)

其实不需要用fetch来处理下载,直接用window.location.href或者创建a标签跳转即可——浏览器的导航请求不受CORS限制,能完美绕开这类问题:

viewHandler = (fileID) => { 
  // 方式1:直接跳转(如果token允许放在URL参数里)
  window.location.href = `http://localhost:8000/download/${fileID}?token=${token}`;
  
  // 方式2:创建a标签(适合需要自定义下载文件名的场景)
  const a = document.createElement('a');
  a.href = `http://localhost:8000/download/${fileID}`;
  a.download = 'sample.pdf';
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
};

如果必须在请求头里带Authorization,那还是得用fetch的方式,但一定要确保后端CORS配置完全正确。

最后验证步骤

  1. 重启后端服务,确保CORS配置生效
  2. 打开浏览器控制台的Network标签,查看请求的响应头是否包含Access-Control-Allow-Origin: http://localhost:3000
  3. 检查fileID拼接后的URL是否和后端实际文件路径匹配

内容的提问来源于stack exchange,提问作者zahraei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:04:45