You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Facebook Graph API v23.0上传视频时通过fetch调用<UPLOAD_SESSION_ID>出现CORS错误

使用Facebook Graph API v23.0上传视频时通过fetch调用<UPLOAD_SESSION_ID>出现CORS错误

我之前也遇到过几乎一模一样的问题——Postman里测试一切顺畅,一到浏览器用fetch就炸CORS,太头疼了!咱们先理清楚为啥会这样:Postman是服务器端的请求工具,不受浏览器同源策略的限制,但浏览器端的fetch请求必须遵守CORS规则,Facebook的API服务器只会允许预先在应用后台配置过的合法域名发起请求,而且你代码里还有几个小问题直接加重了这个情况。

先搞懂核心问题:CORS错误的本质

Facebook的Graph API针对浏览器端的请求有严格的Origin校验,你手动设置Origin: ''不仅没用,反而会让服务器觉得这个请求不合法——浏览器会自动发送当前页面的真实Origin,而如果这个Origin没在你的Facebook应用后台登记过,服务器就会直接拒绝,抛出CORS错误。另外,你代码里的body: '@FILE_SRC'是Postman专属的语法,浏览器根本认不得这是什么东西。

解决方案1:最安全可靠——通过后端代理上传(强烈推荐)

直接在浏览器端调用Facebook的上传接口不仅有CORS问题,还会暴露你的Access Token——这玩意儿要是被用户在开发者工具里扒走,你的Page权限就彻底没了!正确的做法是让你的后端服务器当中间代理:浏览器把文件传给你的后端,后端再调用Facebook的API上传,后端请求不受CORS限制,还能保护Token不泄露。

举个简单的Node.js/Express代理例子:

// 后端代码(Node.js + Express + multer)
const express = require('express');
const fetch = require('node-fetch');
const multer = require('multer');
const app = express();
const upload = multer(); // 处理文件上传

// 代理上传接口
app.post('/proxy-facebook-upload', upload.single('video'), async (req, res) => {
  const { uploadSessionId, accessToken, sig, fileOffset } = req.body;
  const videoFile = req.file;

  try {
    const fbResponse = await fetch(
      `https://graph.facebook.com/v23.0/upload:${uploadSessionId}?sig=${sig}`,
      {
        method: 'POST',
        headers: {
          'Authorization': `OAuth ${accessToken}`,
          'file_offset': fileOffset,
          'Content-Type': videoFile.mimetype
        },
        body: videoFile.buffer
      }
    );
    const result = await fbResponse.json();
    res.json(result);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.listen(3001, () => console.log('代理服务器跑在3001端口啦'));

然后浏览器端只需要把文件传给自己的后端:

// 前端代码
const videoInput = document.querySelector('input[type="file"]');
videoInput.addEventListener('change', async () => {
  const file = videoInput.files[0];
  const formData = new FormData();
  formData.append('video', file);
  formData.append('uploadSessionId', '<你的上传会话ID>');
  // 注意:Access Token要存在后端,别在前端传!这里只是示意参数
  formData.append('accessToken', '<后端存储的合法Token>');
  formData.append('sig', '<你的请求签名>');
  formData.append('fileOffset', '0');

  try {
    const response = await fetch('/proxy-facebook-upload', {
      method: 'POST',
      body: formData
    });
    const result = await response.json();
    console.log('上传进度:', result);
  } catch (err) {
    console.error('上传失败:', err);
  }
});

解决方案2:非要在浏览器端试?那得先改这几个地方(不推荐)

如果你只是想快速测试,非要在浏览器端直接调用,那得先把代码里的坑填上:

  1. 删掉手动设置的Origin头:浏览器会自动发送当前页面的Origin,你手动设空会被浏览器忽略,反而触发服务器的安全校验。
  2. 把body: '@FILE_SRC'换成真实的File/Blob对象:这是Postman的写法,浏览器里要直接传用户选择的文件或者Blob。
  3. 在Facebook应用后台登记你的域名:
    • 打开Facebook开发者后台,找到你的应用
    • 进入「设置」>「基本」,把你的网站域名添加到「网站域」里
    • 再到「产品」>「Facebook登录」>「设置」,把域名添加到「有效的OAuth重定向URI」里

修正后的前端代码:

// 前端测试代码(仅用于测试,生产环境别这么干!)
const videoInput = document.querySelector('input[type="file"]');
videoInput.addEventListener('change', async () => {
  const file = videoInput.files[0];
  const uploadSessionId = '<你的上传会话ID>';
  const accessToken = '<你的Access Token>';
  const sig = '<你的请求签名>';

  try {
    const response = await fetch(
      `https://graph.facebook.com/v23.0/upload:${uploadSessionId}?sig=${sig}`,
      {
        method: 'POST',
        headers: {
          'Authorization': `OAuth ${accessToken}`,
          'file_offset': '0', // 后续上传分段要更新这个值
          'Content-Type': file.type
        },
        body: file // 直接传File对象
      }
    );
    const result = await response.json();
    console.log('上传响应:', result);
  } catch (err) {
    console.error('CORS或其他错误:', err);
  }
});

最后再啰嗦一句

生产环境一定要用后端代理!不仅能解决CORS问题,还能避免Access Token泄露的致命风险——我之前就是图省事在前端直接传Token,结果被人薅了Page权限,折腾了好几天才找回来,血的教训啊!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 10:08:05