// components/media/UploadFile.js
import React, { useContext } from "react";
import { Upload, message, Button } from "antd";
import { UploadOutlined } from "@ant-design/icons";
import { AuthContext } from "../../context/auth";

const UploadFile = () => {
  const [auth, setAuth] = useContext(AuthContext);

  const props = {
    name: "file",
    action: `${process.env.NEXT_PUBLIC_API}/upload-image-file`,
    headers: {
      Authorization: `Bearer ${auth.token}`,
    },
    onChange(info) {
      if (info.file.status !== "uploading") {
        //   console.log(info.file, info.fileList);
      }
      if (info.file.status === "done") {
        // console.log("############ UPLOADED ============> ", info.file.response);
        message.success(`${info.file.name} file uploaded successfully`);
      } else if (info.file.status === "error") {
        message.error(`${info.file.name} file upload failed.`);
      }
    },
    onDrop(e) {
      console.log("Dropped files", e.dataTransfer.files);
    },
  };

  return (
    <Upload {...props} maxCount={1}>
      <Button icon={<UploadOutlined />}>Click to Upload</Button>
    </Upload>
  );
};

export default UploadFile;

Backend route and controller to upload image/file using formdata (express-formidable)

// route
import formidable from "express-formidable";

router.post(
  "/upload-image-file",
  formidable(),
  requireSignin,
  isAdmin,
  uploadImageFile
);

// controller
export const uploadImageFile = async (req, res) => {
  //   console.log(req.files); // [] of File {}
  try {
    // console.log(req.body.image);
    const result = await cloudinary.uploader.upload(req.files.file.path);
    // console.log("uploaded image url => ", result);

    res.json({
      url: result.secure_url,
      public_id: result.public_id,
    });
  } catch (err) {
    console.log(err);
  }
};