You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Node.js调用LinkedIn API V2上传视频遇403错误求助

Troubleshooting 403 Error When Uploading Video to LinkedIn API V2 via Node.js

我明白你遇到的困扰——用Node.js实现LinkedIn视频上传时碰到403错误,但CURL却能正常工作,这种情况确实让人头疼。我们来一步步排查问题所在,并且给出可行的解决方案:

可能的问题根源

  1. Request库的流式上传缺陷
    Request库已经停止维护,它在处理流式请求体时,经常会出现Content-Length头缺失或计算错误的情况。而LinkedIn背后的AWS S3存储服务对这个头的校验很严格,缺失或错误就会直接返回403。CURL会自动计算并设置这个头,但Request的默认行为做不到这一点。

  2. 文件写入的完整性问题
    虽然你监听了close事件,但createWriteStreamclose事件可能在文件完全刷入磁盘前触发,导致上传时读取的文件不完整,进而触发权限或校验错误。

  3. URL参数的意外编码
    LinkedIn返回的uploadUrl包含签名、过期时间等敏感查询参数,Request可能会对这些参数做不必要的URL编码,导致签名失效,最终返回403。

修复方案:替换为现代HTTP库并优化流程

推荐使用axios(或got)这类维护活跃的库,它们对流式上传的支持更可靠。下面是优化后的代码:

const axios = require('axios');
const fs = require('fs');
const { pipeline } = require('stream/promises');

// 下载视频(如果已有本地文件可跳过此步骤)
async function downloadVideo() {
  const videoResponse = await axios.get('https://assets.mixkit.co/videos/2125/2125-720.mp4', {
    responseType: 'stream'
  });
  // 使用pipeline确保文件完全写入磁盘
  await pipeline(videoResponse.data, fs.createWriteStream('video.mp4'));
}

async function uploadToLinkedIn(uploadUrl) {
  const fileStats = fs.statSync('video.mp4');
  const fileStream = fs.createReadStream('video.mp4');

  try {
    const uploadResponse = await axios.post(uploadUrl, fileStream, {
      headers: {
        "x-amz-server-side-encryption-aws-kms-key-id": "MY_ID",
        "x-amz-server-side-encryption": "aws:kms",
        "Content-Type": "application/octet-stream",
        // 显式设置Content-Length,这是解决403的关键
        "Content-Length": fileStats.size,
        // 可选:添加CURL默认发送的Expect头
        "Expect": "100-continue"
      },
      // 取消内容长度限制,避免大视频上传失败
      maxContentLength: Infinity,
      maxBodyLength: Infinity
    });

    return {
      response: uploadResponse,
      url: uploadUrl
    };
  } catch (error) {
    console.error('上传失败详情:', error.response?.status, error.response?.data);
    throw error;
  }
}

// 执行完整流程
downloadVideo()
  .then(() => uploadToLinkedIn(uploadUrl))
  .then(result => console.log('上传成功:', result))
  .catch(err => console.error('流程出错:', err));

额外排查建议

  • 对比CURL的请求头:用curl -v执行成功的命令,把所有请求头和Node.js代码中的头做对比,确保没有遗漏或差异。
  • 验证uploadUrl完整性:确保代码中使用的uploadUrl和LinkedIn返回的完全一致,没有被修改或编码。
  • 检查KMS密钥权限:确认你的KMS密钥允许LinkedIn的存储服务访问,权限配置错误也会导致403。

内容的提问来源于stack exchange,提问作者MQ_pa_43

火山引擎 最新活动