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

分离Sharp模块后Cloudinary上传报Empty file(400)错误求助

问题原因分析

这个错误的核心问题是异步操作没有正确等待,导致Cloudinary在文件还没完全写入磁盘时就尝试读取上传,自然得到"Empty file"的错误。

咱们对比下前后代码的差异:

  • 原代码里你用await等待了sharp(...).toFile(...)完成,因为toFile是异步方法,会返回一个Promise,只有等它执行完毕,压缩后的文件才真正写入磁盘,后续上传操作才能拿到完整的文件内容。
  • 但分离后的item函数只是调用了Sharp的链式方法,既没有返回这个异步操作的Promise,也没在调用时等待它完成。控制器里调用item(req.file)后立刻执行上传,这时候文件可能还在写入过程中,甚至还没被创建,Cloudinary读取到的自然是空文件。
修复方案

你需要调整item函数的异步处理逻辑,并在调用时确保等待文件写入完成:

1. 修改item函数,返回异步操作的Promise

let item = async (req) => {
  // 返回Sharp的toFile方法生成的Promise,让外部可以await它
  return sharp(req.buffer)
    .resize(848, 480)
    .toFormat("jpeg")
    .jpeg({ quality: 90, chromaSubsampling: '4:4:4' })
    .toFile('./public/compressed/' + req.originalname);
}

如果不想用async关键字,直接返回Promise也能达到效果:

let item = (req) => {
  return sharp(req.buffer)
    .resize(848, 480)
    .toFormat("jpeg")
    .jpeg({ quality: 90, chromaSubsampling: '4:4:4' })
    .toFile('./public/compressed/' + req.originalname);
}

2. 在控制器调用时添加await

确保文件完全写入磁盘后,再执行Cloudinary的上传操作:

// 等待压缩文件写入完成
await item(req.file);
const uploadResult = await cloudinary.uploader.upload('./public/compressed/' + req.file.originalname);
console.log(req.file, ' FILE ');
fs.unlinkSync('./public/compressed/' + req.file.originalname);

额外优化建议

为了避免异常情况(比如文件写入失败)导致后续操作出错,建议用try/catch/finally包裹整个流程,保证临时文件能被清理:

try {
  await item(req.file);
  const uploadResult = await cloudinary.uploader.upload('./public/compressed/' + req.file.originalname);
  console.log('上传成功:', uploadResult);
} catch (err) {
  console.error('处理流程出错:', err);
} finally {
  // 无论成功失败,都尝试删除临时文件,避免磁盘占用
  try {
    fs.unlinkSync('./public/compressed/' + req.file.originalname);
  } catch (unlinkErr) {
    console.warn('删除临时文件失败:', unlinkErr);
  }
}

内容的提问来源于stack exchange,提问作者Thomas Bui

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 20:12:32