从 multer 磁盘存储上传到 S3 后无法从上传文件夹中删除文件

问题描述 投票:0回答:1

创建或更新项目时,我必须上传多个图像,因此我使用 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,但都给出了相同的错误

node.js amazon-web-services express amazon-s3 multer
1个回答
0
投票
  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);
现在用于确保等待并正确处理文件删除。

尝试这些改变

© www.soinside.com 2019 - 2024. All rights reserved.