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.