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

Node.js Lambda中Axios上传文件至Dailymotion仅传首段停滞问题排查

问题:Node.js Lambda函数上传文件至Dailymotion仅上传首段后停滞

我尝试通过Node.js Lambda函数将文件上传至Dailymotion,使用了如下代码:

// Download the original file to the `tmp` folder of Lambda.
await axios.get('https://cdn.mysite.com/source.mp4', {
  responseType: 'stream'
})
.then( response => {
  response.data.pipe(fs.createWriteStream('/tmp/video.mp4'));
})
.catch(error => {
  console.log(error);
});

const form = new FormData();
form.append('file', fs.createReadStream('/tmp/video.mp4'));

// Post the file to Dailymotion API.
axios.post('https://upload-xx.xxx.dailymotion.com/upload?uuid=xxxxx&seal=xxxxx&extra=xxxxx', form, {
  headers: {
    ...form.getHeaders,
    'Content-Type': 'multipart/formdata',
    'Content-Length': fs.statSync('/tmp/video.mp4').size
  },
})
.then(response => {
  console.log(response);
})
.catch(error => {
  console.log(error);
});

我可通过URL https://upload-xx.xxx.dailymotion.com/progress?uuid=xxxxx 查看上传进度,但发现仅上传文件首段后便停滞,且未收到任何报错或响应。请问我遗漏了什么?


问题排查与修复方案

1. 文件下载未等待写入完成就启动上传

你用await等待了axios.get请求完成,但response.data.pipe(fs.createWriteStream('/tmp/video.mp4'))是异步写入操作,await并不会等待文件写入完成就执行后续的上传代码。此时读取/tmp/video.mp4时,文件可能只写入了一部分,导致上传到Dailymotion的内容不完整,上传停滞。

修复方式:将文件写入操作包装成Promise,等待写入完成后再执行上传:

// 替换原下载代码
await new Promise((resolve, reject) => {
  axios.get('https://cdn.mysite.com/source.mp4', { responseType: 'stream' })
    .then(response => {
      const writeStream = fs.createWriteStream('/tmp/video.mp4');
      response.data.pipe(writeStream);
      writeStream.on('finish', resolve);
      writeStream.on('error', reject);
    })
    .catch(reject);
});

2. FormData头部配置错误

  • form.getHeaders是一个方法,需要调用form.getHeaders()才能获取正确的头部对象,原代码中没有调用方法,导致头部信息错误。
  • 手动设置Content-Type: 'multipart/formdata'会覆盖FormData自动生成的正确头部(FormData的头部会包含boundary参数,这是multipart/form-data请求必需的),导致服务端无法正确解析请求体。
  • 手动设置Content-Length没有必要,且如果文件还未写完就获取文件大小,会导致长度不准确,FormData和axios会自动处理Content-Length。

修复方式:移除手动设置的Content-Type和Content-Length,正确调用getHeaders()方法:

// 替换原上传的headers配置
headers: {
  ...form.getHeaders(),
  // 移除手动设置的Content-Type和Content-Length
}

3. Lambda临时目录的注意事项

Lambda的/tmp目录有空间限制(默认512MB),如果你的视频文件超过这个大小,会导致写入失败,进而上传不完整。可以检查文件大小是否超出限制。

修复后的完整代码示例

const axios = require('axios');
const fs = require('fs');
const FormData = require('form-data');

exports.handler = async (event) => {
  // 1. 下载文件到Lambda临时目录,等待写入完成
  await new Promise((resolve, reject) => {
    axios.get('https://cdn.mysite.com/source.mp4', { responseType: 'stream' })
      .then(response => {
        const writeStream = fs.createWriteStream('/tmp/video.mp4');
        response.data.pipe(writeStream);
        
        writeStream.on('finish', () => {
          console.log('文件下载并写入完成');
          resolve();
        });
        
        writeStream.on('error', (err) => {
          console.error('文件写入失败:', err);
          reject(err);
        });
      })
      .catch(err => {
        console.error('文件下载失败:', err);
        reject(err);
      });
  });

  // 2. 构建FormData
  const form = new FormData();
  form.append('file', fs.createReadStream('/tmp/video.mp4'));

  // 3. 上传到Dailymotion API
  try {
    const response = await axios.post(
      'https://upload-xx.xxx.dailymotion.com/upload?uuid=xxxxx&seal=xxxxx&extra=xxxxx',
      form,
      {
        headers: {
          ...form.getHeaders(),
          // 可添加其他必要的头部,比如Authorization(如果需要)
        },
        // 可选:添加超时配置,避免无响应停滞
        timeout: 300000 // 5分钟超时
      }
    );
    console.log('上传成功:', response.data);
    return { statusCode: 200, body: JSON.stringify('上传成功') };
  } catch (error) {
    console.error('上传失败:', error.response?.data || error.message);
    return { statusCode: 500, body: JSON.stringify('上传失败') };
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 17:36:23