分离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
相关产品推荐
相关产品推荐

