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

MERN栈仅更新标题描述时出现Cloudinary图片404错误

问题描述

在MERN栈项目中仅更新文章的title和description字段时,出现图片未找到错误,具体错误信息如下:

博客文章错误:{
message: '资源未找到 - https://res.cloudinary.com/cloud_name/image/upload/v1700847934/blog-mern-app/kzg1lxdqfnt2asls0mgq.jpg',
name: 'Error',
http_code: 404
}

创建文章控制器代码

const createPostController = async (req, res) => {
try {
    const { title, description, image } = req.body;
    if(!title){
        return res.status(400).json({message:"invalid title"});
    }
    if(!description){
        return res.status(400).json({message:"invalid description"});
    }
    if(!image){
        return res.status(400).json({message:"invalid image"});
    }
    const uploadPhoto = await cloudinary.uploader.upload(image, { folder: "blog-mern-app" });
    const createPost = new Post({ title, description, image: { public_id: uploadPhoto.public_id, url: uploadPhoto.secure_url } });
    await createPost.save();
    res.status(201).json({success:true, message:"post created successully", createPost});
} catch (error) {
    res.status(500).json({success:false, message: "Error Creating The Blog post"})
}
}

更新文章控制器代码

const updatePostController = async (req, res) => {
try {
    const { title, description, image } = req.body;
    const currentPost = await Post.findById(req.params.id);
    if (!currentPost) {
        return res.status(404).json({ message: "Post not found" });
    }
    if(!image){
        return res.status(404).json({message:"image is compulsary"});
    }
    if (image) {
        if (currentPost.image) {
            const currentImgId = currentPost.image.public_id;
            await cloudinary.uploader.destroy(currentImgId);
        }
        const uploadNewImg = await cloudinary.uploader.upload(image, { folder: "blog-mern-app" });
        currentPost.image = {public_id:uploadNewImg.public_id, url:uploadNewImg.secure_url};
    }
    currentPost.title = title;
    currentPost.description = description;
    await currentPost.save();
    res.status(201).json({ success:true, message:"updated post successfully", currentPost});
} catch (error) {
    console.error("error in blog post:", error);
    res.status(500).json({success:false, message: "error in updating blog post", error:error.message });
}
}
错误原因分析
  1. 强制要求图片参数:更新控制器中存在if(!image){return res.status(404).json({message:"image is compulsary"});}的判断,导致仅更新文本字段时必须传入image参数,不符合实际需求。
  2. 无效图片上传逻辑:如果前端为了满足必填要求传入旧的图片URL,后端会尝试将该URL重新上传至Cloudinary。若该URL对应的资源已被销毁或不可访问,就会触发Cloudinary返回404资源未找到错误。
  3. 文本字段无判断覆盖:直接赋值currentPost.title = title会导致空值覆盖原有内容,存在数据风险。
解决方案

1. 修改更新控制器逻辑

移除图片必填限制,仅在传入image参数时处理图片更新,同时增加文本字段的非空判断:

const updatePostController = async (req, res) => {
try {
    const { title, description, image } = req.body;
    const currentPost = await Post.findById(req.params.id);
    if (!currentPost) {
        return res.status(404).json({ message: "Post not found" });
    }

    // 仅传入image时才执行图片更新逻辑
    if (image) {
        // 销毁旧图片(存在则执行)
        if (currentPost.image?.public_id) {
            await cloudinary.uploader.destroy(currentPost.image.public_id);
        }
        // 上传新图片
        const uploadNewImg = await cloudinary.uploader.upload(image, { folder: "blog-mern-app" });
        currentPost.image = {public_id:uploadNewImg.public_id, url:uploadNewImg.secure_url};
    }

    // 仅传入有效内容时更新文本字段
    if (title) currentPost.title = title;
    if (description) currentPost.description = description;

    await currentPost.save();
    // 更新成功使用标准200状态码
    res.status(200).json({ success:true, message:"updated post successfully", currentPost});
} catch (error) {
    console.error("error in blog post:", error);
    res.status(500).json({success:false, message: "error in updating blog post", error:error.message });
}
}

2. 前端请求优化

仅更新文本字段时,请求体中不要包含image字段,避免触发后端的图片更新逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 11:05:25