在网站上播放R2存储桶音乐并避免CORS错误并启用206 Partial Content

926 字
5 分钟
在网站上播放R2存储桶音乐并避免CORS错误并启用206 Partial Content

前言#

最近想在博客加入音乐播放器,发现现有的Meting API对QQ音乐的支持比较弱,而我还是用Apple Music的,这导致我也不好弄个QQ会员之类的,于是我将我的歌单下载下来并放在R2存储桶上面,发现网站使用URL的时候会有CORS错误,之前参考的文章是这篇文章,我是按照那篇文章使用Cloudflare Workers进行反代,并且使用EdgeOne进行国内外分流,发现会有CORS错误,于是为了解决CORS错误有了这篇文章。

为什么有这个错误#

就是因为跨域访问没有加入应该加入的请求头。

Cloudflare Workers修改方案#

我根据这篇文章关于Cloudflare Workers的代码进行了修改,修改内容如下:

export default {
async fetch(request, env) {
try {
// 1. === 防盗链 / Allowed Domains ===
const ALLOWED_DOMAINS = (env.ALLOWED_DOMAINS_STR || "")
.split(',')
.map(d => d.trim())
.filter(d => d);
const origin = request.headers.get("Origin") || "";
const referer = request.headers.get("Referer") || "";
if (ALLOWED_DOMAINS.length > 0) {
const isAllowed = ALLOWED_DOMAINS.some(d =>
origin.startsWith(d) || referer.startsWith(d)
);
if (!isAllowed) {
return new Response("Forbidden: 防盗链已启用", {
status: 403,
headers: { "Access-Control-Allow-Origin": "*" }
});
}
}
// 2. === 请求方法检查 ===
if (!["GET", "HEAD"].includes(request.method)) {
return new Response("Method Not Allowed", { status: 405 });
}
const url = new URL(request.url);
const objectKey = decodeURIComponent(url.pathname.slice(1));
// 3. === 准备基础响应头 (CORS 等) ===
const baseHeaders = new Headers();
baseHeaders.set("Access-Control-Allow-Origin", origin || ALLOWED_DOMAINS[0] || "*");
baseHeaders.set("Access-Control-Allow-Headers", "Range");
baseHeaders.set("Access-Control-Expose-Headers", "Content-Length, Content-Range, ETag");
baseHeaders.set("Accept-Ranges", "bytes");
baseHeaders.set("Cache-Control", "public, max-age=259200, immutable");
const rangeHeader = request.headers.get("Range");
// ==========================================
// 场景 A: 带有 Range 头的请求 (视频播放/拖动)
// ==========================================
if (rangeHeader) {
// 先获取文件元数据(不读取内容),拿到文件总大小
const objectHead = await env.R2_BUCKET.head(objectKey);
if (!objectHead) {
return new Response("Not Found", { status: 404 });
}
const total = objectHead.size;
const match = /^bytes=(\d*)-(\d*)$/.exec(rangeHeader);
if (!match) {
return new Response("Range Not Satisfiable", { status: 416 });
}
const start = match[1] ? parseInt(match[1]) : 0;
const end = match[2] ? parseInt(match[2]) : total - 1;
// 简单的越界检查
if (start >= total || end >= total || start > end) {
baseHeaders.set("Content-Range", `bytes */${total}`);
return new Response("Range Not Satisfiable", { status: 416, headers: baseHeaders });
}
// 【关键修复】:告诉 R2 只去取这一段数据,不要把整个文件读入内存
const object = await env.R2_BUCKET.get(objectKey, {
range: { offset: start, length: end - start + 1 },
onlyIf: request.headers // 支持 ETag 验证
});
if (!object) {
return new Response("Not Found", { status: 404 });
}
// 设置 206 专用头
object.writeHttpMetadata(baseHeaders);
baseHeaders.set("etag", object.httpEtag);
baseHeaders.set("Content-Range", `bytes ${start}-${end}/${total}`);
baseHeaders.set("Content-Length", (end - start + 1).toString());
return new Response(object.body, {
status: 206,
headers: baseHeaders
});
}
// ==========================================
// 场景 B: 普通请求 (下载完整文件)
// ==========================================
const object = await env.R2_BUCKET.get(objectKey, {
onlyIf: request.headers
});
if (!object) {
return new Response("Not Found", { status: 404 });
}
object.writeHttpMetadata(baseHeaders);
baseHeaders.set("etag", object.httpEtag);
return new Response(object.body, {
headers: baseHeaders
});
} catch (err) {
console.error("Worker Error:", err);
return new Response("Internal Server Error\n" + err.message, { status: 500 });
}
}
};

由于我本人没有那个能力,也没那个心思去学习前端的知识,所以上面的代码使用Gemini进行修改的,换成这个代码之后就能够正常使用了

EdgeOne 修改方案#

通过规则引擎加入修改 HTTP 节点响应头的方式规避CORS错误

EdgeOne规则引擎设置
EdgeOne规则引擎设置

修改类型响应头名称响应头值作用说明
增加Access-Control-Allow-Origin*或你的站点域名允许所有域名访问
增加Access-Control-Allow-MethodsGET, HEAD, OPTIONS明确告知支持的方法(音频流常用)
增加Access-Control-Allow-HeadersRange, Authorization, Content-Type允许浏览器发送这些请求头
增加Access-Control-Expose-HeadersContent-Range, Content-Length必须:允许播放器读取分片大小,显示总时长
增加Access-Control-Max-Age86400减少预检请求次数,提升加载速度
增加Accept-Rangesbytes告知浏览器此链接支持进度条拖动

按如图表设置后可以解决CORS错误并使用206状态

总结#

没啥好总结的,就这样可以通过R2存储桶来让网站播放音乐

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

在网站上播放R2存储桶音乐并避免CORS错误并启用206 Partial Content
https://blog.backsoon0.top/posts/music-cors-206/
作者
Backsoon0
发布于
2026-02-11
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
Backsoon0
我要什么,我不知道,我不是无欲无求,我只是不知所求。
公告
正在搭建网站
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
4
分类
3
标签
4
总字数
5,182
运行时长
0
最后活动
0 天前

目录