Efficient Image Processing and Storage for Web and App Assets Using Sharp and AWS

I am creating an API. In which I am storing marketplace data web images and app images.

So what I want to do is that I want to reduce the size of the image and then convert that image into webp. and want to store it on AWS. But I am getting the error.

Error: Error compressing and converting the image: TypeError [ERR_INVALID_ARG_TYPE]: The “path” argument must be of type string or an instance of Buffer or URL. Received undefined.
at readFile (fs.js:343:10)
at internal/util.js:341:30
at new Promise ()
at readFile (internal/util.js:340:12)
at convertAndCompress

To convert the image I am using the Sharp library. But what the sharp library does is it accesses the image from its local path and then converts the image. However, on the live website, we cannot access the local file path.

This is my middleware function of converting the image. If my environment is local then I am storing the image locally otherwise on upload it on AWS s3. This code is working fine in local but in live I am getting error.

add_marketplace_banner_images: async (req, res, next) => {
      // const admin_id = req.user.user_id;
      const admin_id = 12;
      try {
        const upload = multer({
          storage: Config.environment === "local" ? storage_marketplace_banner_images : multerS3Config,
          limits: {
            fileSize: 6242880, // Compliant: 5MB
          },
          fileFilter: (req, file, cb) => {
            const allowedExtensions = ['.png', '.jpg', '.webp', '.jpeg'];
            const ext = path.extname(file.originalname).toLowerCase();
            if (allowedExtensions.includes(ext)) {
              const validateImage = validatingImage(module.exports.schemas.marketplace_banner_data);
              if (validateImage) {
                cb(null, true);
              }
            } else {
              cb(new Error('Only images with .png, .jpg, .webp, and .jpeg extensions are allowed!'), false);
            }
          },
        }).fields([
          { name: "web_image", maxCount: 1 },
          { name: "app_image", maxCount: 1 },
        ]);

        upload(req, res, async function (err) {
          if (err) {
            return res.status(400).json({ status: 2, errors: { file: err.message } });
          }

          const processImage = async (fieldName) => {
            if (req.files && req.files[fieldName]) {
              const originalImage = req.files[fieldName][0];
              const compressedImage = await sharp(originalImage.path)
                .webp({ quality: 80 })
                .toBuffer()
                .catch((err) => {
                  console.error("Error compressing and converting the image:", err);
                  throw err;
                });

              if (Config.environment === "local") {
                const outputPath = `${originalImage.destination}/${originalImage.filename}.webp`;
                await fs.promises.writeFile(outputPath, compressedImage);
                fs.unlinkSync(originalImage.path); // Remove the original image file

                req.files[fieldName] = [{
                  fieldname: fieldName,
                  originalname: `${path.parse(originalImage.originalname).name}.webp`,
                  encoding: '7bit',
                  mimetype: 'image/webp',
                  destination: path.dirname(originalImage.destination),
                  filename: path.basename(outputPath),
                  path: outputPath,
                  size: fs.statSync(outputPath).size,
                }];
              } else {
                const image_name = `${Math.floor(Date.now() / 1000)}-${admin_id}-${uuid()}`;
                const s3Params = {
                  Bucket: Config.aws.bucketName,
                  Key: `uploads/marketplace_banner_image/${image_name}.webp`,
                  Body: compressedImage,
                  ContentType: "image/webp",
                };
                await s3.putObject(s3Params).promise();
              }
            }
          };

          const processedImages = await Promise.allSettled([
            req.files.web_image && processImage("web_image"),
            req.files.app_image && processImage("app_image"),
          ]);

          const rejectedImages = processedImages.filter((result) => result.status === "rejected");
          if (rejectedImages.length > 0) {
            console.error("Error processing images:", rejectedImages.map((result) => result.reason));
            return res.status(500).json({ status: 3, message: "Error processing images" });
          }

          next();
        });
      } catch (err) {
        console.error("Server error:", err);
        res.status(500).json({ status: 3, message: "Server error" });
      }
    },

Is there any way to achieve this task? I don’t want to store the image somewhere, convert it, and then store it on AWS. Apart from this, is there any other solution to do this task?