使用no-cors模式的Fetch检测指定URL文件是否存在的问题
需要检测指定URL下的HTML文件是否存在,FTP服务器URL格式为:
http://10.200.11.60/ftpfiles/ftpfiles/<file_name>.html
在本地React项目中,尝试用HEAD方法发起fetch请求检测文件:
const result = await fetch('http://10.200.11.60/ftpfiles/ftpfiles/<file_name>.html', { method: 'HEAD' });
但遇到CORS错误:
Access to fetch at 'http://10.200.11.60/ftpfiles/ftpfiles/<file_name>.html' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
切换到no-cors模式后,网络面板能看到200或404响应,但console.log返回的response状态始终为0。需要解决:如何获取实际响应状态?或者在无法修改FTP服务器CORS配置的情况下,有没有更好的文件存在检测方法?
由于浏览器同源策略限制,无法修改目标服务器CORS配置时,前端直接请求无法获取完整响应信息,以下是几种替代方案:
1. 搭建后端代理服务
在React项目配套的后端(如Node.js、Java等)新增代理接口,由后端发起请求检测文件状态,前端调用该接口即可。后端不受浏览器同源策略限制,能正常获取响应状态。
示例Node.js代理接口(基于Express):
const express = require('express'); const axios = require('axios'); const app = express(); app.get('/check-file', async (req, res) => { const fileName = req.query.fileName; const targetUrl = `http://10.200.11.60/ftpfiles/ftpfiles/${fileName}.html`; try { const response = await axios.head(targetUrl); res.status(200).json({ exists: true, status: response.status }); } catch (error) { if (error.response?.status === 404) { res.status(200).json({ exists: false, status: 404 }); } else { res.status(500).json({ error: '文件检测失败' }); } } }); app.listen(3001, () => console.log('代理服务运行在3001端口'));
前端调用示例:
const checkFileExists = async (fileName) => { const res = await fetch(`http://localhost:3001/check-file?fileName=${fileName}`); const data = await res.json(); return data.exists; };
2. 利用资源加载事件间接判断
通过创建iframe元素加载目标HTML文件,监听load和error事件间接判断文件是否存在:
const checkFileExists = (fileName) => { return new Promise((resolve) => { const iframe = document.createElement('iframe'); iframe.style.display = 'none'; // 添加时间戳避免缓存干扰 iframe.src = `http://10.200.11.60/ftpfiles/ftpfiles/${fileName}.html?t=${Date.now()}`; iframe.onload = () => { resolve(true); document.body.removeChild(iframe); }; iframe.onerror = () => { resolve(false); document.body.removeChild(iframe); }; document.body.appendChild(iframe); }); };
注意:这种方法无法区分404和其他服务器错误(如500),只能判断资源是否成功加载。
3. JSONP(仅服务器支持时可用)
若FTP对应的Web服务支持返回JSONP格式响应,可通过JSONP绕开CORS,但该方式仅适用于GET请求,且需要服务器配合,对于静态HTML文件来说可行性较低,一般不推荐。
内容的提问来源于stack exchange,提问作者Przemek Wit

