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

Node.js使用got.stream上传流至form-data时遭遇411长度要求错误

解决Storyblock API(S3底层)外部URL流上传的411 Length Required错误

本地文件用createReadStream上传到Storyblock API完全正常,但用got.stream拉取外部URL上传时,会返回411 Length Required错误。核心原因是S3(以及基于它的Storyblock API)要求请求必须携带Content-Length头,而两种流的特性存在关键差异:

  • createReadStream返回的是文件系统流,自带文件大小元数据,form-data库能自动读取并生成正确的Content-Length请求头;
  • got.stream返回的是HTTP请求流,没有内置的文件大小信息,form-data无法自动计算整个请求的总长度,导致请求缺少必要头触发错误。

解决方案一:提前获取文件大小,手动指定给form-data

先发送HEAD请求拿到远程文件的Content-Length,再在追加流时传给form-data的knownLength参数:

import FormData from 'form-data';
import got from 'got';

async function uploadFromExternalUrl(externalUrl, apiEndpoint) {
  // 发送HEAD请求获取文件大小
  const headRes = await got.head(externalUrl, { decompress: false });
  const fileSize = parseInt(headRes.headers['content-length'], 10);

  const form = new FormData();
  // 追加流时指定已知长度
  form.append('file', got.stream(externalUrl, { decompress: false }), {
    knownLength: fileSize
  });

  // 提交表单到API
  const submitRes = await form.submit(apiEndpoint);
  console.log('上传成功,状态码:', submitRes.statusCode);
}

// 调用示例
uploadFromExternalUrl('https://example.com/remote-file.jpg', 'YOUR_STORYBLOCK_UPLOAD_ENDPOINT')
  .catch(err => console.error('上传失败:', err));

解决方案二:先下载远程文件到本地临时文件,再上传

如果远程服务器不支持HEAD请求,或者文件体积不大,可以先把文件下载到本地临时文件,再用熟悉的本地流方式上传:

import { createReadStream, createWriteStream } from 'fs';
import { pipeline } from 'stream/promises';
import FormData from 'form-data';
import got from 'got';
import { tmpdir } from 'os';
import { join } from 'path';

async function uploadFromExternalUrl(externalUrl, apiEndpoint) {
  // 创建临时文件路径
  const tempFile = join(tmpdir(), `temp-upload-${Date.now()}.jpg`);

  // 下载远程文件到临时文件
  await pipeline(
    got.stream(externalUrl, { decompress: false }),
    createWriteStream(tempFile)
  );

  // 用本地文件流上传
  const form = new FormData();
  form.append('file', createReadStream(tempFile));
  const submitRes = await form.submit(apiEndpoint);

  console.log('上传成功,状态码:', submitRes.statusCode);
  
  // 可选:清理临时文件
  // await fs.promises.unlink(tempFile);
}

// 调用示例
uploadFromExternalUrl('https://example.com/remote-file.jpg', 'YOUR_STORYBLOCK_UPLOAD_ENDPOINT')
  .catch(err => console.error('上传失败:', err));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:53:27