Node.js应用使用FormData上传远程图片遇TypeError问题求助
解决Node.js中用FormData上传远程图片的问题
错误原因
你直接传入result.body(Node.js的ReadableStream)到form.append时出错,是因为FormData的实现(不管是form-data库还是Node.js原生)不支持直接接收这种原始流类型,内部尝试监听流事件时找不到对应的方法,所以抛出TypeError: source.on is not a function。
而你尝试result.blob()没效果,大概率是因为没指定文件名,或者使用的FormData实现和Blob对象不兼容。
解决方案
根据你使用的FormData实现,分两种情况处理:
情况1:使用常用的form-data库(Node.js项目主流选择)
如果你的项目依赖的是form-data库(通过npm install form-data安装),可以用以下两种方式:
方式1:将远程图片转为Buffer后上传
const FormData = require('form-data'); const fetch = require('node-fetch'); async function uploadRemoteImage() { const form = new FormData(); const imageUrl = '你的远程图片URL'; // 获取远程图片响应 const imgResponse = await fetch(imageUrl); if (!imgResponse.ok) throw new Error(`获取图片失败:${imgResponse.statusText}`); // 将响应转为Buffer const imgBuffer = await imgResponse.buffer(); // 追加到FormData,必须指定文件名和内容类型 form.append('file', imgBuffer, { filename: 'image.jpg', // 自定义文件名,后端靠这个识别文件 contentType: imgResponse.headers.get('content-type') || 'image/jpeg' }); // 发送上传请求,必须携带form-data生成的headers const uploadRes = await fetch('你的上传接口URL', { method: 'POST', body: form, headers: form.getHeaders() }); const result = await uploadRes.json(); console.log(result); }
方式2:直接传入响应流上传(适合大文件)
const FormData = require('form-data'); const fetch = require('node-fetch'); async function uploadRemoteImage() { const form = new FormData(); const imageUrl = '你的远程图片URL'; const imgResponse = await fetch(imageUrl); if (!imgResponse.ok) throw new Error(`获取图片失败:${imgResponse.statusText}`); // 直接传入响应流,同样要指定文件名和内容类型 form.append('file', imgResponse.body, { filename: 'image.jpg', contentType: imgResponse.headers.get('content-type') || 'image/jpeg' }); const uploadRes = await fetch('你的上传接口URL', { method: 'POST', body: form, headers: form.getHeaders() }); const result = await uploadRes.json(); console.log(result); }
情况2:使用Node.js 18+原生FormData
如果你的Node.js版本在18及以上,可以用原生的FormData(无需额外安装库),但需要将Blob转为File对象:
const { FormData } = require('node:formdata'); const fetch = require('node-fetch'); async function uploadRemoteImage() { const form = new FormData(); const imageUrl = '你的远程图片URL'; const imgResponse = await fetch(imageUrl); if (!imgResponse.ok) throw new Error(`获取图片失败:${imgResponse.statusText}`); // 获取Blob对象并转为File(必须指定文件名) const imgBlob = await imgResponse.blob(); const imgFile = new File([imgBlob], 'image.jpg', { type: imgResponse.headers.get('content-type') || 'image/jpeg' }); // 追加到FormData form.append('file', imgFile); // 发送上传请求 const uploadRes = await fetch('你的上传接口URL', { method: 'POST', body: form }); const result = await uploadRes.json(); console.log(result); }
关键注意事项
- 必须指定文件名:后端需要通过文件名识别文件字段,不指定的话可能无法解析出正确的文件。
form-data库要带专属headers:用这个库时,必须通过form.getHeaders()生成请求头,否则后端会无法解析FormData格式。- 内容类型要匹配:尽量从响应头获取真实的
content-type,避免后端识别文件类型出错。
内容的提问来源于stack exchange,提问作者fabpicca
相关产品推荐
相关产品推荐

