创建或更新项目时,我必须上传多个图像,因此我使用 multer diskstorage 将项目存储在上传文件夹中,然后上传到 S3。我想在上传到 s3 后从磁盘存储中删除这些文件,因为我不想堵塞磁盘资源,但是,当我尝试使用 fs unlink 删除文件时,出现以下错误:
Error deleting file uploads\22812ab9-e8a0-49de-9d4f-f637e5d9d1c2.jpg: [Error: EPERM: operation not permitted, unlink 'D:\_projects\bitkart\server\uploads\22812ab9-e8a0-49de-9d4f-f637e5d9d1c2.jpg']
我无法直接上传到 s3,因为我必须重构很多代码,有什么方法可以使用 multer 来完成并解决错误吗?
我尝试在创建项目控制器中使用 try catch :
export const createItem = async (req: Request, res: Response) => {
try {
const userId = req.user?.id;
const {
title,
description,
price,
room_no,
hostel_no,
year_of_purchase,
category,
contact_no,
} = req.body;
const existingItem = await Item.findOne({ title, seller: userId });
if (existingItem) {
return res
.status(400)
.json({ message: "You already have an item with this title" });
}
// Calculate total size
const totalSize = (req.files as Express.Multer.File[]).reduce(
(acc: number, file: Express.Multer.File) => acc + file.size,
0
);
if (totalSize > MAX_FILE_SIZE) {
return res
.status(400)
.json({ message: "Total file size exceeds the 25 MB limit." });
}
// Resize and upload each image
const imageDetails = [];
for (const file of req.files as Express.Multer.File[]) {
const filePath = path.join("uploads", file.filename);
try {
// Resize the image and convert it to webp format
const buffer = await sharp(filePath).toFormat("webp").toBuffer();
const imageName = randomImageName();
const params = {
Bucket: bucketName!,
Key: imageName,
Body: buffer,
ContentType: file.mimetype,
};
const command = new PutObjectCommand(params);
await s3.send(command);
imageDetails.push({ key: imageName });
} catch (uploadError) {
console.error(`Error uploading file ${file.filename}:`, uploadError);
return res.status(500).json({ message: "Error uploading file." });
} finally {
// Ensure the file is deleted from the disk after processing
try {
await fs.promises.unlink(filePath);
console.log(`Successfully deleted ${filePath}`);
} catch (unlinkError) {
console.error(`Error deleting file ${filePath}:`, unlinkError);
}
}
}
const newItem = new Item({
title,
description,
price,
room_no,
hostel_no,
year_of_purchase,
category,
seller: userId,
images: imageDetails,
contact_no,
});
await newItem.save();
await User.findByIdAndUpdate(userId, { $push: { items: newItem._id } });
res.status(201).json({ message: "Item created Successfully", newItem });
} catch (error) {
res.status(500).json({ message: "Server error", error });
}
};
我也尝试简单地尝试在 updateitems 中取消链接:
export const updateImages = async (req: Request, res: Response) => {
try {
const userId = req.user?.id;
const itemId = req.params.id;
const item = await Item.findById(itemId);
if (!item || item.seller.toString() !== userId) {
return res
.status(404)
.json({ message: "Item not found or not authorized" });
}
if (item.images.length >= 4) {
return res
.status(400)
.json({ message: "You cannot upload more than 4 images" });
}
if (!req.files || req.files.length === 0) {
return res.status(400).json({ message: "Please upload images" });
}
// Calculate total size of new images
const totalSize = (req.files as Express.Multer.File[]).reduce(
(acc: number, file: Express.Multer.File) => acc + file.size,
0
);
if (totalSize > MAX_FILE_SIZE) {
return res
.status(400)
.json({ message: "Total file size exceeds the 25 MB limit." });
}
// Resize and upload new images
const newImages = [];
for (const file of req.files as Express.Multer.File[]) {
const filePath = path.join("uploads", file.filename);
// Check if the file exists
if (!fs.existsSync(filePath)) {
return res.status(400).json({ message: `File not found: ${filePath}` });
}
// Resize the image
const buffer = await sharp(filePath).toFormat("webp").toBuffer();
const imageName = randomImageName();
const params = {
Bucket: bucketName,
Key: imageName,
Body: buffer,
ContentType: file.mimetype,
};
const command = new PutObjectCommand(params);
await s3.send(command);
newImages.push({
url: `${process.env.CLOUDFRONT_DOMAIN}${imageName}`,
key: imageName,
});
// Delete the file from disk after uploading to S3
fs.promises.unlink(filePath);
}
// Update images in item
const updatedImages = [...item.images, ...newImages];
item.images = updatedImages.slice(0, 4); // Ensure only 4 images are kept
await item.save();
res.json({ message: "Images updated successfully", item });
} catch (error) {
console.log(error);
res.status(500).json({ message: "Server error", error });
}
};
我也尝试过仅使用 unlink、unlink async、promisify,但都给出了相同的错误
try {
// Resize the image
const buffer = await sharp(filePath).toFormat("webp").toBuffer();
const imageName = randomImageName();
const params = {
Bucket: bucketName,
Key: imageName,
Body: buffer,
ContentType: file.mimetype,
};
const command = new PutObjectCommand(params);
await s3.send(command);
newImages.push({
url: `${process.env.CLOUDFRONT_DOMAIN}${imageName}`,
key: imageName,
});
// Delete the file from disk after uploading to S3
await fs.promises.unlink(filePath);
console.log(`Successfully deleted ${filePath}`);
} catch (err) {
console.error(`Error processing file ${filePath}:`, err);
return res.status(500).json({ message: "Server error", error: err });
}
}
我将(S3 上传、文件删除)包装在 try-catch 块中,以有效捕获和处理任何错误。
await fs.promises.unlink(filePath);
现在用于确保等待并正确处理文件删除。
尝试这些改变