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

Node.js调用上传接口时请求为空,文件上传失败

问题:使用FormData+Axios上传本地文件,服务器接收为空

我尝试通过上传API把本地文件传到远程服务器,用Form Data附加文件,但服务器那边始终收到空文件,以下是我的代码:

let filename = 'NJ-09_13_22-nodup.csv'
let noDupFile = config.OUTPUT_PATH + '/' + filename
const noDupFileReadStream = fs.createReadStream(noDupFile)
    .on('data', function (chunk) {
          console.log('chunk', chunk)
       }).on('end', async function () {
           console.log('noDupFileReadStream end')
           const form = new FormData()
           form.append('file', noDupFileReadStream)

           const requestConfig = {
                  headers: {
                     ...form.getHeaders()
                  },
                  httpAgent: new http.Agent({ keepAlive: true, 
                       maxSockets: Infinity })
                }
           axios.post(`${config.XMINDER_URL}/utils/upload`, form, 
                    requestConfig).then(function (response) {
                        console.log(response.data.url)
                    }).catch(function (error) {
                          console.log(error)
                   })
               })

问题根源

你犯了一个关键错误:在可读流的end事件触发后,才把流附加到FormData。

fs.createReadStream创建的是一次性可读流,当end事件触发时,流已经把所有数据读取完毕,内部指针走到末尾,此时再把这个流传给FormData,它已经没有任何数据可以被发送,服务器自然收到空文件。

另外,你监听data事件打印chunk的操作,会直接消耗流的数据(没有做暂停或重处理),进一步导致流提前耗尽。


修正方案

直接将未被消耗的可读流附加到FormData即可,不需要等到流读取结束。FormData会自动处理流的读取和上传过程,无需手动监听data或end事件。

同时建议给form.append加上文件名参数,确保服务器能正确识别文件名称(多数后端框架依赖这个参数解析文件)。

修正后的代码:

const filename = 'NJ-09_13_22-nodup.csv'
const noDupFile = `${config.OUTPUT_PATH}/${filename}`
const noDupFileReadStream = fs.createReadStream(noDupFile)

// 直接创建FormData并附加流,无需等待end事件
const form = new FormData()
// 第三个参数指定文件名,后端可正确获取文件名
form.append('file', noDupFileReadStream, filename)

const requestConfig = {
  headers: {
    ...form.getHeaders()
  },
  httpAgent: new http.Agent({ keepAlive: true, maxSockets: Infinity })
}

axios.post(`${config.XMINDER_URL}/utils/upload`, form, requestConfig)
  .then(response => {
    console.log(response.data.url)
  })
  .catch(error => {
    console.log(error)
  })

额外说明

  • 如果需要验证文件是否存在,可在创建流前用fs.existsSync或fs.promises.access做检查,避免因文件不存在导致上传失败
  • 无需手动监听data事件,除非你需要做加密、压缩这类额外数据流处理,否则会消耗流数据导致上传异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 16:55:26