We'll use the following package next-s3-upload
bun add next-s3-upload
Go to the Cloudflare dashboard and create and R2 bucket.
- Once the bucket is created. Select the bucket. Go to it's settings and edit the CORS policy.
[
{
"AllowedOrigins": ["*"],
"AllowedMethods": ["PUT", "POST", "GET"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag"]
}
]
- Copy the
S3 API
from the bucket details of the settings. It will look like this.
https://<Account_ID>.r2.cloudflarestorage.com/<name-of-bucket>
-
Go to Public access setting of the bucket and set a custom domain to access the files of the bucket.
-
Now create the
ACCESS ID
andSECRET_ID
api tokens to connect to the R2 storage fromhttps://dash.cloudflare.com/<Account_ID>/r2/api-tokens
-
Save these as the environment variables in
.env
file in the root of the NextJs project.
Create an API route that will process the upload of the file.
import { APIRoute } from "next-s3-upload";
export default APIRoute.configure({
accessKeyId: process.env.R2_ACESSS_ID,
secretAccessKey: process.env.R2_SECRET_ID,
bucket: "name-of-bucket",
region: "us-east-1",
endpoint: "`https://<ACCOUNT_ID>.r2.cloudflarestorage.com` endpoint.",
});
Last step is to create a react component which use the API to uploads the file and return the public access URL.
"use client";
import { useState } from "react";
import { usePresignedUpload } from "next-s3-upload";
export default function UploadComponent() {
let [imageUrl, setImageUrl] = useState();
let { FileInput, openFileDialog, uploadToS3 } = usePresignedUpload();
let handleFileChange = async (file) => {
let { url } = await uploadToS3(file);
setImageUrl(
url.replace(
"https://<Account_ID>.r2.cloudflarestorage.com/<bucket-name>",
"https://custom-domain.domain.com"
)
);
};
return (
<div>
<FileInput onChange={handleFileChange} />
<button onClick={openFileDialog}>Upload file</button>
{imageUrl && <img src={imageUrl} />}
</div>
);
}