DEV Community

Cover image for Image upload by NextJs Api in Public Folder
Tanvir Ahammed
Tanvir Ahammed

Posted on

Image upload by NextJs Api in Public Folder

** FIRST ENSURE THAT YOU HAVE NEXT JS PROJECT**

THEN INSTALL THESE PACKAGE

npm i multer
npm i path
Enter fullscreen mode Exit fullscreen mode

BACK-END
api\upload.ts

import { NextApiRequest, NextApiResponse } from "next";
import multer from "multer";
import path from "path";
export const config = {
  api: {
    bodyParser: false,
  },
};
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const dateFolder = new Date().toISOString().split("T")[0]; // Use date as the folder name
    const uploadPath = path.join("./public/uploads", dateFolder);

    // Create the folder if it doesn't exist
    require("fs").mkdirSync(uploadPath, { recursive: true });

    cb(null, uploadPath);
  },
  filename: (req, file, cb) => {
    cb(
      null,
      `${file.fieldname}-${Date.now()}${file.originalname.substring(
        file.originalname.lastIndexOf(".")
      )}`
    );
  },
});

const upload = multer({ storage });

const uploadApi = async (req: NextApiRequest, res: NextApiResponse) => {
  try {
    await new Promise<void>((resolve, reject) => {
      upload.single("image")(req as any, res as any, (err) => {
        if (err) {
          return reject(err);
        }
        resolve();
      });
    });

    // Access the 'file' property after the multer middleware processes the file
    const uploadedFile = req.file;

    if (!uploadedFile) {
      return res.status(400).json({ error: "No file uploaded" });
    }

    // Assuming the uploaded file is saved in the public/uploads folder
    const dateFolder = new Date().toISOString().split("T")[0];
    const fileName = uploadedFile.filename;
    const filePath = path.join("uploads", dateFolder, fileName);

    res.status(200).json({ message: "Image uploaded successfully", filePath });
  } catch (error) {
    console.log(error);

    res.status(500).json({ error: "Error uploading image" });
  }
};

export default uploadApi;

Enter fullscreen mode Exit fullscreen mode

next.config.js

async rewrites() {
    return [
      {
        source: "/uploads/:path*",
        destination: "/uploads/:path*", // Adjust this path based on your project structure
      },
    ];
  },
Enter fullscreen mode Exit fullscreen mode

** FRONT-END **
components\UploadForm.tsx

// Your React component

import React, { useState } from "react";

const UploadForm = () => {
  const [file, setFile] = useState<any>(null);

  const handleFileChange = (e: any) => {
    setFile(e.target.files[0]);
  };

  const handleUpload = async () => {
    const formData = new FormData();
    formData.append("image", file);

    try {
      const response = await fetch("/api/upload", {
        method: "POST",
        body: formData,
      });

      if (response.ok) {
        // Parse the JSON response
        const responseData = await response.json();

        // Access the data from the server
        console.log("Image uploaded successfully", responseData);
      } else {
        console.error("Error uploading image");
      }
    } catch (error) {
      console.error("Error uploading image", error);
    }
  };

  return (
    <div>
      <input type="file" onChange={handleFileChange} />
      <button onClick={handleUpload}>Upload</button>
    </div>
  );
};

export default UploadForm;

Enter fullscreen mode Exit fullscreen mode

FRONT-END UI

Uploaded image with a response

BACK-END UPLOADED FOLDER

Image uploaded folder

Top comments (2)

Collapse
 
yousuf4you profile image
Yousuf Ahamad •

Is it work, after the production build??

Collapse
 
mikdiet profile image
Mikhail Dieterle •

I'm getting Property 'file' does not exist on type 'NextApiRequest' on req.file.

Though I have @types/multer installed.