Pixiv - Miv4t
在网站上播放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错误

| 修改类型 | 响应头名称 | 响应头值 | 作用说明 |
|---|---|---|---|
| 增加 | Access-Control-Allow-Origin | *或你的站点域名 | 允许所有域名访问 |
| 增加 | Access-Control-Allow-Methods | GET, HEAD, OPTIONS | 明确告知支持的方法(音频流常用) |
| 增加 | Access-Control-Allow-Headers | Range, Authorization, Content-Type | 允许浏览器发送这些请求头 |
| 增加 | Access-Control-Expose-Headers | Content-Range, Content-Length | 必须:允许播放器读取分片大小,显示总时长 |
| 增加 | Access-Control-Max-Age | 86400 | 减少预检请求次数,提升加载速度 |
| 增加 | Accept-Ranges | bytes | 告知浏览器此链接支持进度条拖动 |
按如图表设置后可以解决CORS错误并使用206状态
总结
没啥好总结的,就这样可以通过R2存储桶来让网站播放音乐
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
在网站上播放R2存储桶音乐并避免CORS错误并启用206 Partial Content
https://blog.backsoon0.top/posts/music-cors-206/ 相关文章 智能推荐
1
使用Cloudflare R2搭建图床并用阿里ESA/腾讯EdgeOne进行加速
图片 搭建一个小图床
2
尽可能得减小图片大小
图片 通过一些方式减小图片大小
3
你好 Backsoon0 blog
其他 网站搭建过程
随机文章 随机推荐
backsoon0