Node.js Express对接Cloudinary如何仅更新指定图片并删除冗余旧文件
实现方案
首先你需要先新增一个Cloudinary图片删除的工具函数,同时修正原有上传函数的错误处理逻辑,再调整editBlog控制器的执行顺序即可。
1. 修正并新增Cloudinary工具函数
// 修正原有上传函数的错误处理:原代码误将cloudinary返回的res当成express响应对象,会触发报错 const cloudinaryUploadImage = async image => { return new Promise((resolve, reject) => { cloudinary.uploader.upload(image , (err, res) => { if (err) reject(err) resolve({ img_url: res.secure_url, img_id: res.public_id }); }) }) } // 新增:Cloudinary图片删除函数 const cloudinaryDeleteImage = async (publicId) => { return new Promise((resolve, reject) => { cloudinary.uploader.destroy(publicId, (err, result) => { if (err) reject(err) resolve(result) }) }) }
2. 调整editBlog控制器代码
exports.editBlog = async (req, res) => { const { id } = req.params; const { title, category, content } = req.body; const blogImages = req.files; try { // 1. 先查询原博客数据,拿到旧图片ID const oldBlog = await Blog.findById(id); if (!oldBlog) { return res.status(404).json({ message: '博客数据不存在' }); } const updates = { title, category, content }; let oldImageIds = []; // 2. 有新上传图片时才处理图片替换逻辑 if (blogImages?.length > 0) { // 上传新图片到Cloudinary const updated_images = await Promise.all(blogImages.map((img) => cloudinaryUploadImage(img.path))); updates.images = updated_images; // 收集旧图片ID,等数据库更新成功后再删除 oldImageIds = oldBlog.images.map(img => img.img_id); } // 3. 执行数据库更新 const updated_data = await Blog.findOneAndUpdate( { _id: id }, { $set: updates }, { new: true } ); // 4. 数据库更新成功后,异步删除旧图片(不阻塞主流程,删除失败可单独打日志处理) if (oldImageIds.length > 0) { Promise.all(oldImageIds.map(id => cloudinaryDeleteImage(id))) .catch(err => console.log('Cloudinary旧图片删除失败:', err)) } res.status(200).json({ message: '数据更新成功', result: updated_data }); } catch (error) { res.status(500).json({ message: 'Internal server error', error }); } };
核心逻辑说明
- 优先查询原博客数据,避免更新不存在的资源,同时拿到旧图片的public_id用于后续删除
- 移除了原代码中无新图片就返回400的判断,支持仅修改文字内容不换图的场景
- 数据库更新成功后再执行旧图片删除操作,避免数据库更新失败时旧图被误删,导致数据丢失
- 旧图片删除逻辑做异步处理不阻塞主响应流程,删除失败不会影响用户正常的更新操作
内容的提问来源于stack exchange,提问作者program_bumble_bee
相关产品推荐
相关产品推荐

