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

使用fetch发送POST请求时遭遇415不支持媒体类型错误

问题分析与修复方案

首先明确:fs.createReadStream读取文件的操作本身没问题,但你把ReadStream直接拼接到urlencoded字符串里的做法完全错误,同时对curl示例的理解有偏差,这才导致了415(不支持媒体类型)的错误。

核心问题拆解

1. 对curl命令的误解

你贴的curl命令里,-d "@path/filename.mp4"是curl的特殊语法——它会读取文件内容作为表单参数值,但application/x-www-form-urlencoded这种编码格式根本不适合传输二进制文件(比如MP4),二进制数据经过urlencode后会损坏,而且效率极低。大概率这个curl示例本身就有问题,或者API文档存在误导,正常文件上传应该用multipart/form-data格式。

2. fetch代码的致命错误

  • 你把fileData(ReadStream对象)直接拼到字符串里,最终生成的请求体是api_key=xxx&[object Object],这完全不是有效的urlencoded内容,服务器根本无法解析。
  • 用application/x-www-form-urlencoded传输二进制文件本身就是错误选择,这也是服务器返回415的直接原因。

正确实现方式

如果API支持表单上传文件(绝大多数文件上传API都用这个),用FormData构建请求体才是正确做法,Node.js环境下的实现如下:

const fs = require('fs');
const path = require('path');
// Node.js 18+内置FormData,低于18版本需要先执行npm install form-data
const FormData = require('form-data');

const filePath = path.join(__dirname, '/video/video.mp4');
const form = new FormData();
form.append('api_key', API_KEY);
// 注意:这里的参数名(比如"file")要和API要求一致,需确认文档或curl示例隐含的参数名
form.append('file', fs.createReadStream(filePath));

fetch(url, {
  method: 'POST',
  body: form,
  // 不需要手动设置Content-Type,FormData会自动生成带boundary的正确请求头
}).then(async (res) => {
  console.log('状态码:', res.status);
  console.log('服务器返回:', await res.text());
}).catch(err => {
  console.error('请求出错:', err);
});

如果API硬要你用application/x-www-form-urlencoded(极不推荐,仅适合小文件),你得先把文件读成Buffer再转base64:

const fs = require('fs').promises;
const path = require('path');
const querystring = require('querystring');

async function uploadVideo() {
  const filePath = path.join(__dirname, '/video/video.mp4');
  const fileBuffer = await fs.readFile(filePath);
  
  const formData = querystring.stringify({
    api_key: API_KEY,
    file: fileBuffer.toString('base64') // 假设API接受base64编码的文件内容
  });

  const res = await fetch(url, {
    method: 'POST',
    body: formData,
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  });

  console.log('状态码:', res.status);
  console.log('服务器返回:', await res.text());
}

uploadVideo().catch(err => console.error('上传失败:', err));

额外注意点

  • 优先用multipart/form-data,这是HTTP传输二进制文件的标准方式。
  • 确认API要求的文件参数名称(你的curl示例缺失参数名,正常应该是-d "file=@path/filename.mp4",这个参数名要和form.append里的一致)。
  • 415错误就是服务器不认可你传的Content-Type,务必匹配API文档要求的格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:25:20