I'll show you how to upload images in Next.js with Base64 encoding. We will use the next/image
component to display the base64 encoded image.
Let's build a simple form to upload an image.
import type { NextPage } from "next";
import Image from "next/image";
import { useState } from "react";
const Upload: NextPage = () => {
// State to store the file
const [file, setFile] = useState<File | null>(null);
// State to store the base64
const [base64, setBase64] = useState<string | null>(null);
return (
<>
<h1>Upload Image</h1>
<form method="POST" encType="multipart/form-data">
<input type="file" name="avatar" accept="image/*" />
<button type="submit">Upload</button>
</form>
</>
);
};
export default Upload;
Add a method to handle the file change event.
// When the file is selected, set the file state
const onFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!e.target.files) {
return;
}
setFile(e.target.files[0]);
};
Add another method to handle the click event.
// On click, clear the input value
const onClick = (e: React.MouseEvent<HTMLInputElement>) => {
e.currentTarget.value = "";
};
Now let's add the toBase64
method to convert the file to base64.
// Convert a file to base64 string
const toBase64 = (file: File) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
resolve(fileReader.result);
};
fileReader.onerror = (error) => {
reject(error);
};
});
};
Next add the method to handle the form submit event.
// On submit, upload the file
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!file) {
return;
}
// Convert the file to base64
const base64 = await toBase64(file as File);
setBase64(base64 as string);
// You can upload the base64 to your server here
await fetch("/api/your-upload-endpoint", {
method: "POST",
body: JSON.stringify({ base64 }),
headers: {
"Content-Type": "application/json",
},
});
// Clear the states after upload
setFile(null);
setBase64(null);
};
Wire up the methods to handle the file change and click events.
<form method="POST" encType="multipart/form-data" onSubmit={handleSubmit}>
<input
type="file"
name="avatar"
accept="image/*"
onChange={onFileChange}
onClick={onClick}
/>
<button type="submit">Upload</button>
</form>
Finally, let's add the Image
component to display the base64 encoded image.
{
base64 && (
<Image src={base64} width={300} height={400} alt="Uploaded Image" />
);
}
Here's the complete code for the upload form component.
import type { NextPage } from "next";
import Image from "next/image";
import { useState } from "react";
const Upload: NextPage = () => {
// State to store the file
const [file, setFile] = useState<File | null>(null);
// State to store the base64
const [base64, setBase64] = useState<string | null>(null);
// When the file is selected, set the file state
const onFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!e.target.files) {
return;
}
setFile(e.target.files[0]);
};
// On click, clear the input value
const onClick = (e: React.MouseEvent<HTMLInputElement>) => {
e.currentTarget.value = "";
};
// On submit, upload the file
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!file) {
return;
}
// Convert the file to base64
const base64 = await toBase64(file as File);
setBase64(base64 as string);
// You can upload the base64 to your server here
await fetch("/api/your-upload-endpoint", {
method: "POST",
body: JSON.stringify({ base64 }),
headers: {
"Content-Type": "application/json",
},
});
// Clear the states after upload
setFile(null);
setBase64(null);
};
return (
<>
<h1>Upload Image</h1>
<form method="POST" encType="multipart/form-data" onSubmit={handleSubmit}>
<input
type="file"
name="avatar"
accept="image/*"
onChange={onFileChange}
onClick={onClick}
/>
<button type="submit">Upload</button>
</form>
{base64 && (
<Image src={base64} width={300} height={400} alt="Uploaded Image" />
)}
</>
);
};
// Convert a file to base64 string
const toBase64 = (file: File) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
resolve(fileReader.result);
};
fileReader.onerror = (error) => {
reject(error);
};
});
};
export default Upload;