在开发基于 Web 的应用时,我们经常会遇到前端 JavaScript 代码无法读取存储在阿里云 OSS(Object Storage Service)上的资源的问题。本文将详细记录一次典型的 CORS(跨域资源共享)问题的排查过程及解决方案。
问题描述
场景:
我们编写了一个 Node.js 脚本抓取数据并上传到阿里云 OSS。然后,我们在 Hexo 博客的前端页面中使用 JavaScript (fetch 或 XMLHttpRequest) 去请求这个 JSON 数据文件,以便渲染图表或列表。
现象:
- 直接访问正常:将文件的 OSS URL 粘贴到浏览器地址栏,可以正常下载或预览文件,HTTP 状态码为 200。
- 代码请求失败:当网页代码尝试读取该文件时,浏览器控制台(Console)报错,通常显示 “Network Error” 或 “Failed to fetch”。
- 开发者工具查看:在 Network 面板中,请求状态可能显示为 (failed) 或 CORS error,无法查看 Response Data。
问题分析
这是一个经典的 跨域(Cross-Origin Resource Sharing, CORS) 问题。
什么是跨域?
浏览器的 同源策略(Same-Origin Policy) 是一项安全机制,它限制了从一个源(协议 + 域名 + 端口)加载的文档或脚本如何与来自另一个源的资源进行交互。
当您的博客(例如 https://wenjun.me)尝试去请求阿里云 OSS 的资源(例如 https://bucket-name.oss-cn-shanghai.aliyuncs.com/data.json)时,由于域名不同,浏览器会发起跨域请求。
为什么直接访问可以?
当您直接在浏览器地址栏输入 URL 时,这是一个“导航”行为,不受同源策略限制。但当您在 JS 代码中使用 fetch 或 axios 发起请求时,浏览器会严格检查服务器返回的响应头。
验证方法
我们可以使用 curl 命令来模拟请求并查看响应头:
|
如果响应头中 缺失 Access-Control-Allow-Origin 字段,那么浏览器就会拦截这次请求的响应数据,报跨域错误。
解决方案
要解决这个问题,我们需要在服务端(阿里云 OSS)配置允许跨域访问。
步骤一:登录阿里云 OSS 控制台
- 登录 阿里云 OSS 管理控制台。
- 在左侧导航栏找到并点击您的 Bucket 名称(例如
file201503)。
步骤二:配置跨域规则
进入 数据安全 -> 跨域设置 (CORS)。
点击 创建规则。
按如下配置填写:
来源 (Allowed Origins):
- 建议填写您的网站域名,例如
https://wenjun.me。 - 如果用于测试,可以填
*(允许所有域名访问,但在生产环境建议限制域名)。
- 建议填写您的网站域名,例如
允许 Methods (Allowed Methods):
- 勾选
GET(如果只是读取文件)。 - 如果有上传需求,可能需要勾选
PUT,POST等。
- 勾选
允许 Headers (Allowed Headers):
- 填写
*(允许所有请求头)。
- 填写
暴露 Headers (Expose Headers):
- 填写
ETag。 - 这允许前端 JS 代码访问
ETag响应头,有时候缓存验证需要用到。
- 填写
点击 确定 保存。
配置生效通常是秒级的。配置完成后,再次刷新您的网页,数据应该就能正常加载了。
进阶优化:设置正确的文件元数据
除了解决跨域问题,为了让文件在浏览器中体验更好,建议在上传时设置正确的文件头:
- Content-Type: 设置为
application/json(对于 JSON 文件)。这样浏览器知道它是一个数据文件而不是普通文本。 - Content-Disposition: 设置为
inline。inline:浏览器会尝试在窗口内直接预览内容。attachment:浏览器会强制弹出下载框。
在 Node.js (ali-oss SDK) 中的代码示例:
|
通过以上配置,您可以完美解决前端从阿里云 OSS 读取数据的跨域问题,并优化用户体验。