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

博客应用实现无图片发布功能时遭遇url未定义错误求助

实现博客文章图片非必填的解决方案

1. 修改 createPost 控制器逻辑

创建文章时,仅当用户上传了图片(file 存在)时才调用Cloudinary上传接口,否则跳过上传步骤:

const createPost = async (req, res) => {
    const { title, file, tags, body, authorUsername } = req.body;

    // 初始化image对象,无图片时为空对象
    let image = {};
    if (file) {
        // 仅当有图片时才执行上传
        const { url, public_id: publicId } = await uploadToCloudinary(file, 'Posts');
        image = { url, publicId };
    }

    const author = await User.findOne({ username: authorUsername }).exec();

    const formattedTags = tags
        .trim()
        .split(',')
        .map(w => w.trim().replace(/ /g, '-'));

    const createdPost = await Post.create({
        title,
        image, // 无图片时传入空对象,mongoose会自动处理
        body,
        author: author._id,
    });

    // 以下原有逻辑保持不变
    author.followers.map(followerId => {
        (async () => {
            await postNotification(author._id, createdPost._id, followerId);
        })();
    });

    await createTags(formattedTags, createdPost);

    author.posts.push(createdPost._id);

    await author.save();

    res.status(200).json(createdPost.toObject({ getters: true }));
};

2. 修改 updatePost 控制器逻辑

更新文章时,仅当用户提供了新的图片URL时,才执行上传和旧图片删除操作:

const updatePost = async (req, res) => {
    const authorId = await User.findOne({ username: req.params.username }).exec();
    const { postTitle, postId } = getPostParams(req.params.postUrl);

    // 仅当存在新图片URL时,才执行上传和替换逻辑
    if (req.body.image?.url) {
        const { url, public_id: publicId } = await uploadToCloudinary(req.body.image.url, 'Posts');
        // 删除旧图片
        await cloudinary.uploader.destroy(req.body.image.publicId);
        req.body.image = { url, publicId };
    } else {
        // 无新图片时,删除req.body.image,避免覆盖原有图片数据
        delete req.body.image;
    }

    const formattedTags = req.body.tags
        .trim()
        .split(',')
        .map(w => w.trim().replace(/ /g, '-'));

    const post = await Post.findOne({
        author: authorId,
        title: postTitle,
        _id: postId,
    })
        .populate('author')
        .populate('tags');

    Object.keys(req.body).map(key => {
        if (key !== 'tags') post[key] = req.body[key];
    });

    await updateTags(formattedTags, post);

    await post.save();

    res.status(200).json(post.toObject({ getters: true }));
};

3. 修复删除操作中的图片处理逻辑

避免无图片时调用Cloudinary销毁接口报错:

修改 deletePostsByUserId 函数

posts.forEach(post => {
    (async () => {
        await deleteTags(
            post.tags.map(({ name }) => name),
            post,
            true
        );
        // 仅当存在图片publicId时才销毁
        if (post.image?.publicId) {
            await cloudinary.uploader.destroy(post.image.publicId);
        }
        await Post.deleteOne({ _id: post._id });
    })();
});

修改 deletePost 函数

// 仅当传入了publicId时才销毁图片
if (req.body.publicId) {
    await cloudinary.uploader.destroy(req.body.publicId);
}

4. 确认Post模型配置(无需修改)

你的Post模型已经正确设置了image字段为非必填,无需额外修改:

image: { url: { type: String }, publicId: { type: String } },

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 11:31:03