如何使用multer-storage-cloudinary实现Cloudinary图片删除功能?
解决multer-storage-cloudinary上传后无法获取public_id进行图片删除的问题
核心问题在于你没有把Cloudinary返回的public_id存储到数据库中——而这个值正是调用destroy方法删除图片的关键。下面是一步步的解决方案:
第一步:修改上传逻辑,保存public_id到数据库
multer-storage-cloudinary实际上已经把public_id放在了req.file.filename里(因为你设置了folder: "works",所以这个值是带文件夹路径的完整public_id,比如works/ujrrf13kyil8l5rjccwf)。你需要把这个字段和图片URL一起存入数据库:
首先确保你的Post模型中添加了img_public_id字段(字符串类型),然后修改上传路由:
router.post('/', withAuth, imgUpload.single('work-img'), (req, res) => { console.log(req.file); Post.create({ title: req.body.title, dimension: req.body.dimensions, description: req.body.description, media: req.body.media, img_url: req.file.path, img_public_id: req.file.filename, // 新增:保存public_id到数据库 user_id: req.session.user_id }) .then((dbPostData) => res.json(dbPostData)) .catch((err) => { console.log(err); res.status(500).json(err); }); });
第二步:更新路由中删除旧图片并替换为新图片
在更新时,先查询旧帖子的img_public_id,调用Cloudinary的destroy方法删除旧图,再更新数据库中的新图片信息:
router.put('/:id', withAuth, imgUpload.single('work-img'), async (req, res) => { try { // 1. 查询旧帖子数据 const oldPost = await Post.findByPk(req.params.id); if (!oldPost) { return res.status(404).json({ message: 'No post found with this id' }); } // 2. 准备更新的基础数据 const updateData = { title: req.body.title, dimension: req.body.dimensions, description: req.body.description, media: req.body.media }; // 3. 如果用户上传了新图片,删除旧图并添加新图信息 if (req.file) { // 调用Cloudinary API删除旧图片 await cloudinary.uploader.destroy(oldPost.img_public_id); // 更新图片URL和public_id updateData.img_url = req.file.path; updateData.img_public_id = req.file.filename; } // 4. 执行数据库更新 const [updatedRows] = await Post.update(updateData, { where: { id: req.params.id } }); if (updatedRows === 0) { return res.status(404).json({ message: 'No post found with this id' }); } // 返回更新后的完整帖子数据 const updatedPost = await Post.findByPk(req.params.id); res.json(updatedPost); } catch (err) { console.log(err); res.status(500).json(err); } });
第三步:删除路由中同时删除Cloudinary图片和数据库记录
如果需要删除帖子,记得先删除对应的Cloudinary图片:
router.delete('/:id', withAuth, async (req, res) => { try { const post = await Post.findByPk(req.params.id); if (!post) { return res.status(404).json({ message: 'No post found with this id' }); } // 先删除Cloudinary上的图片 await cloudinary.uploader.destroy(post.img_public_id); // 再删除数据库中的帖子 await Post.destroy({ where: { id: req.params.id } }); res.json({ message: 'Post and associated image deleted successfully' }); } catch (err) { console.log(err); res.status(500).json(err); } });
关键说明
req.file.filename就是Cloudinary的完整public_id(包含你设置的文件夹路径),直接用来调用destroy方法即可。- 使用
async/await可以让异步操作更清晰,避免回调嵌套。 - 更新时要判断用户是否上传了新图片——如果没有上传,就不需要执行删除旧图的操作,也不要更新图片相关字段。
内容的提问来源于stack exchange,提问作者Christopher Concannon




