为什么本地文件用 fetch 请求 JSON 会报 CORS 错误?

Newb.一茹 阅读 297

我最近在本地开发一个静态页面,想用 fetch('data.json') 加载同目录下的 JSON 文件,结果浏览器控制台报错:「Access to fetch at ‘file:///…/data.json’ from origin ‘null’ has been blocked by CORS policy」。明明是本地文件,又没跨域,怎么会触发 CORS?

我已经试过把文件放到 VS Code 的 Live Server 里跑,这样就能正常加载,但直接双击 HTML 文件打开就不行。是不是因为 file:// 协议的问题?有没有办法在不启动服务器的情况下解决?

我来解答 赞 5 收藏
二维码
手机扫码查看
2 条解答
ლ子硕
ლ子硕 Lv1
这个问题的根源确实在于 file:// 协议的特殊性。我来详细解释下:

浏览器出于安全考虑,默认禁止通过 file:// 协议发起的跨源请求,即使是在本地文件系统里。当你直接双击打开 HTML 文件时,浏览器会把当前 origin 识别为 'null',而 file:// 协议下的 JSON 文件也被视为不同源,所以就触发了 CORS 限制。

解决办法有几种,我按推荐顺序说:

1. 最佳方案:使用本地开发服务器(推荐)
用 VS Code 的 Live Server 或者任何轻量级服务器(比如 http-server)都可以。因为这种情况下 origin 变成了 localhost,同源策略就正常了。

2. 如果非要直接打开文件:
对于 Chrome/Edge 可以这样启动(注意这会降低安全性):
chrome.exe --allow-file-access-from-files

或者用 Firefox 的 about:config 里设置:
security.fileuri.strict_origin_policy 改为 false

3. 另一个变通方法是直接把 JSON 数据内联到 JS 文件里:
// 把 data.json 改成 data.js
const data = {"key": "value"}; // 原 JSON 内容

// 然后在 HTML 里



4. 如果只是临时测试,可以尝试用 fetch() 的 catch 捕获错误,然后用 Node.js 的 fs 模块读取文件(仅限测试环境)。

原理上,现代浏览器对 file:// 协议的限制越来越严格,这是为了防止本地文件被恶意网页读取。我建议还是用开发服务器,这才是正经的开发方式。毕竟你后面要部署到 web 服务器上时,迟早要面对这些问题的。

另外注意,用第二种方法修改浏览器设置后,记得测试完就改回来,不然会有安全隐患。
点赞 1
2026-03-09 10:03
司徒心虹
这个问题我当年也踩过坑,说实话浏览器这个报错信息确实容易让人误解。你猜对了,就是 file:// 协议搞的鬼。

问题的根源在于浏览器的安全策略。当你直接双击 HTML 文件打开时,地址栏是 file:/// 开头的,这时候页面的 origin 被浏览器定义为字符串 "null"。注意不是空字符串,而是字符串 "null"。当你用 fetch 请求另一个本地文件时,浏览器会认为这是从一个 origin 为 "null" 的源去访问另一个源,即使它们在同一个文件夹里。

Chrome 和其他现代浏览器出于安全考虑,禁止 file:// 协议的页面发起任何 AJAX 或 fetch 请求。这个设计是为了防止恶意网页读取你本地的文件系统,想象一下如果网页能随意读取你电脑上的文件,那得多危险。

Live Server 能跑通是因为它启动了一个本地 HTTP 服务器,你的页面变成了 http://127.0.0.1:5500,请求 JSON 文件时是同源的,自然就没有 CORS 问题了。

如果你非要不用服务器,有几种方案,但都有局限。

方案一,给 Chrome 加启动参数。关闭所有 Chrome 窗口,然后用命令行启动:

# Windows
chrome --allow-file-access-from-files --disable-web-security --user-data-dir=/tmp/chrome_dev

# Mac
open -a "Google Chrome" --args --allow-file-access-from-files --disable-web-security --user-data-dir=/tmp/chrome_dev


这个方法能跑,但我不建议用。首先每次都要手动启动很麻烦,其次这会关闭浏览器的安全策略,你日常上网千万别用这个模式的浏览器。

方案二,把 JSON 数据直接内嵌到 JS 文件里。如果你的数据是静态的,不经常变动,直接写成一个变量:

// data.js
const localData = {
"users": [
{ "id": 1, "name": "张三" },
{ "id": 2, "name": "李四" }
]
};


然后在 HTML 里用 引入,直接用 localData 这个变量就行。简单粗暴,但失去了 JSON 文件的灵活性。

方案三,如果你只是想快速测试,可以用 Python 一行命令起个服务器。前提是你电脑装了 Python:

# Python 3
cd 你的项目目录
python -m http.server 8080

# 然后访问 http://localhost:8080


或者用 Node.js 的 http-server 包,全局安装后直接运行就行。

说到底,本地开发起个服务器是正道。VS Code 的 Live Server 插件也好,Python 的简易服务器也好,都是几秒钟的事。浏览器的安全策略不是来跟你作对的,是真的在保护用户。我之前为了调试一个本地存储的问题折腾了半天,最后发现就是 file:// 协议下 localStorage 的行为和 http:// 也不一样,坑多了去了。

总结一下,没有服务器的情况下完美解决这个问题的方案基本没有,要么接受安全风险改浏览器参数,要么把数据内嵌,要么老老实实起个本地服务器。建议还是用 Live Server 或者其他本地服务器方案,省心。
点赞 5
2026-03-01 15:00