我正在开发一个社交媒体平台,用户可以将媒体文件(图像、视频等)上传到 Cloudinary,并将该媒体返回的 URL 存储在我的 MongoDB 数据库中。媒体上传成功,但某些情况下数据库保存操作失败。在这种情况下,我想从 Cloudinary 删除上传的媒体以避免出现孤立文件。
我编写了以下代码,其中使用 Cloudinary 进行文件上传,使用 MongoDB 保存发布数据。我使用 Mongoose 事务来确保数据库操作的原子性,如果数据库保存失败,我将调用 cloudinary.uploader.destroy() 从 Cloudinary 的 catch 块中删除媒体。
但是,我担心数据库事务失败后Cloudinary 上的删除操作失败 的情况。在这种情况下,我的媒体将保留在 Cloudinary 上,从而导致不一致。
这是我的代码的相关部分 Cloudinary配置和实用功能
const cloudinary = require('cloudinary').v2;
// Configuration
cloudinary.config({
cloud_name: process.env.CLOUDINARY_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET
});
const opts = {
overwrite:true,
invalidate:true,
resource_type:"auto",
folder: "Socialsphere"
};
// Upload media to cloudinary
exports.cloudinaryUpload = (image) => { // image = base64
return new Promise((resolve, reject) => {
cloudinary.uploader.upload(image, opts, (error, result) => {
if (result && result.secure_url) {
return resolve(result);
}
return reject({message: error.message});
});
});
};
// Delete media from cloudinary
exports.cloudinaryDelete = async (id) => {
await cloudinary.uploader.destroy(id);
};
控制器代码
const Post = require('../Models/Post');
const Profile = require('../Models/Profile');
const mongoose = require('mongoose');
const { cloudinaryDelete, cloudinaryUpload } = require('../Utiles/Cloudinary');
exports.CreateNewPost = async (req, res) => {
// Implementing transaction
const session = await mongoose.startSession();
session.startTransaction();
let cloudinaryResult = null;
try {
const { caption, url, type } = req.body;
const { Email } = req;
if (!url) {
return res.status(409).json({
success: false,
message: 'Post creation failed, try again'
});
}
// Uploading media to Cloudinary
cloudinaryResult = await cloudinaryUpload(url);
const fileUrl = cloudinaryResult.secure_url;
// Saving post to the database
const userPost = new Post({ Url: fileUrl, Caption: caption, Type: type });
await userPost.save({ session });
// Finding user by email and updating their post array
const userProfile = await Profile.findOneAndUpdate(
{ Email: Email },
{ $push: { Post: userPost._id } },
{ new: true, session }
);
if (!userProfile) {
return res.status(404).json({
success: false,
message: 'User not found, please login and try again'
});
}
// Commit the transaction
await session.commitTransaction();
session.endSession();
return res.status(200).json({
success: true,
message: 'Post created successfully'
});
} catch (error) {
console.log(error);
// If any operation fails, delete the uploaded file from Cloudinary
if (cloudinaryResult && cloudinaryResult.public_id) {
await cloudinaryDelete(cloudinaryResult.public_id);
}
// Abort the transaction
await session.abortTransaction();
session.endSession();
return res.status(500).json({
success: false,
message: 'Post creation failed, try again'
});
}
};
我的问题:
如果有任何关于如何改进此流程并使其更加稳健的建议,我将不胜感激。谢谢!
我在 Cloudinary 工作,我可以解决你的第三点: 如果您担心孤立的图像留在 Cloudinary 上,您可以执行以下操作:
public_id
值的列表。这些是应该存在的图像。您也许可以将其作为计划作业,每月/每季度运行一次并清理系统。