Next.js Upload Image to Public Folder
Photo by Skylar Kang from Pexels
Overview
This post is a short demo of how to upload an image to subfolder labeled “\uploads” under the “.\public” folder with Next.JS. Using a page with a file field and a Send to Server button to call a local API that uploads the image to the uploads subfolder under the ./public.
Source Code
GitHub Repo
Prerequisites
New Next.js App
Create a new Next.js application
npx create-next-app@latest
Formidable
Install Formidable for parsing form data.
npm i formidable
MV
Install mv to move the files from temp directory to the public folder.
Vercel recommends that large files should be uploaded to a cloud service like Google Storage Bucket or AWS S3. If moving a file from one location to another using fs it can throw up an error about cross platforms,
npm install mv
Running the Next.JS app
npm run dev
Create the Subfolder
Create a subfolder under ./public labeled uploads. This is where the files will be uploaded.
Upload Image Form
Under pages create a new folder & file “.\pages\uploadform\index.js“. Copy & paste the code below.
import { useState } from "react";export default function PrivatePage(props) { const [image, setImage] = useState(null); const [createObjectURL, setCreateObjectURL] = useState(null); const uploadToClient = (event) => { if (event.target.files && event.target.files[0]) { const i = event.target.files[0]; setImage(i); setCreateObjectURL(URL.createObjectURL(i)); } }; const uploadToServer = async (event) => { const body = new FormData(); // console.log("file", image) body.append("file", image); const response = await fetch("/api/upload", { method: "POST", body }); }; return ( <div> <div> <img src={createObjectURL} /> <h4>Select Image</h4> <input type="file" name="myImage" onChange={uploadToClient} /> <button className="btn btn-primary" type="submit" onClick={uploadToServer} > Send to server </button> </div> </div> );}
API
Create “.\pages\api\upload\index.js“ and copy & paste the source code below/
import { IncomingForm } from 'formidable'import { promises as fs } from 'fs'var mv = require('mv');export const config = { api: { bodyParser: false, }}; export default async (req, res) => { const data = await new Promise((resolve, reject) => { const form = new IncomingForm() form.parse(req, (err, fields, files) => { if (err) return reject(err) console.log(fields, files) console.log(files.file.filepath) var oldPath = files.file.filepath; var newPath = `./public/uploads/${files.file.originalFilename}`; mv(oldPath, newPath, function(err) { }); res.status(200).json({ fields, files }) }) }) }
Running the Demo
Run the application with npm run dev.
When running the application navigate to “http://localhost:3000/uploadform“
Click on Choose File and select an image then click on Send to Server.
Once the file is uploaded it should show up under the “.\public\uploads“
Example: Uploaded an image labeled Service.png