使用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
相关产品推荐
相关产品推荐

