Edge Store to handle file uploads in Next.js
Resources: https://github.com/harshalranjhani/edgestore-resources
The Current State of File Uploads in Next.js
Handling file uploads in Next.js requires setting up a server to manage these uploads and writing a significant amount of boilerplate code. This process can be quite time-consuming and prone to errors, particularly for developers who are aiming to create efficient and reliable applications. Managing file uploads involves several steps, including configuring the server, handling different file types, ensuring secure file storage, and dealing with potential issues like large files or low network conditions.
What is EdgeStore?
EdgeStore is a type-safe Node package that makes it super easy to upload and retrieve files from the cloud. It's designed to cut down on the setup or configuration time, letting you say goodbye to all that extra boilerplate code you'd normally have to write for cloud file uploads. With EdgeStore, managing cloud files becomes straightforward, freeing you up to focus more on building great features for your app.
Using Edgestore in a Next.js project
First let's start by initializing a Next.js project:
npx create-next-app@latest # yarn create next-app
After you're done setting up the Next.js project, you'll be prompted with a few questions, I would suggest going with all the default options, only that we'll be using Typescript in this article, since edgestore is type-safe, why not utilize that right?
Now enter inside your app and install all the dependencies:
npm install # yarn
Now we will install the dependencies required by edgestore:
npm install @edgestore/server @edgestore/react zod # yarn add @edgestore/server @edgestore/react zod
We will start by creating a new account on edgestore. After you're successfully signed up, you can head over to your dashboard where you can create a new project. After creating a new project you will have access to a access key and a secret key.
Add these keys to your .env.local
file:
EDGE_STORE_ACCESS_KEY=your-access-key
EDGE_STORE_SECRET_KEY=your-secret-key
Next, create a folder named api
inside the src/app
directory.
Now create a new file route.ts
inside the src
directory at the location src/app/api/edgestore/[...edgestore]
:
Copy the following into route.ts
:
import { initEdgeStore } from "@edgestore/server";
import { createEdgeStoreNextHandler } from "@edgestore/server/adapters/next/app";
const es = initEdgeStore.create();
const edgeStoreRouter = es.router({
publicFiles: es.fileBucket({
maxSize: 1024 * 1024 * 10, // 10MB
// accept: ["application/pdf"],
}),
});
const handler = createEdgeStoreNextHandler({
router: edgeStoreRouter,
});
export { handler as GET, handler as POST };
export type EdgeStoreRouter = typeof edgeStoreRouter;
Here I've created a file upload bucket where the maximum upload size is 10mb and additionally you can also specify the file extensions to be accepted.
For images, edgestore provides a dedicated bucket called imageBucket
which you can replace with fileBucket
to dedicate it for images.1
Now we will set up the context provider for our frontend: For this we create a new file called edgestore.ts
inside src/lib
:
Copy the following into layout.tsx
:
"use client";
import { type EdgeStoreRouter } from "../app/api/edgestore/[...edgestore]/route";
import { createEdgeStoreProvider } from "@edgestore/react";
const { EdgeStoreProvider, useEdgeStore } =
createEdgeStoreProvider<EdgeStoreRouter>();
export { EdgeStoreProvider, useEdgeStore };
And then we can wrap our app with the EdgeStoreProvider
. Copy the following into src/app/layout.tsx
:
import { EdgeStoreProvider } from "../lib/edgestore";
import "./globals.css";
// ...
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<EdgeStoreProvider>{children}</EdgeStoreProvider>
</body>
</html>
);
}
We can use the useEdgeStore
hook to directly upload files from the frontend.
Inside your page.tsx
copy the following:
"use client";
// ..
import { useEdgeStore } from "../lib/edgestore";
export default function Page() {
// .. state declarations
const { edgestore } = useEdgeStore();
return (
<div className="m-20">
<input
type="file"
onChange={(e) => {
setFile(e.target.files?.[0]);
}}
/>
<button
onClick={async () => {
setUrl(null);
if (file) {
const res = await edgestore.publicFiles.upload({
file,
onProgressChange: (progress) => {
// you can use this to show a progress bar
console.log(progress);
setProgress(progress);
},
});
// you can run some server action or api here
// to add the necessary data to your database
console.log(res);
setUrl(res.url);
setProgress(null);
}
}}
>
Upload
</button>
<div className="mt-10">
{progress !== null && <div>Progress: {progress}%</div>}
{url && (
<div>
URL: <Link href={url}>{url}</Link>
</div>
)}
</div>
</div>
);
}
After this you can try to upload a sample file and you should see something like this after the successful upload:
And that's it! It's actually lightning fast and super easy to upload files to the cloud without having to setup formData or any API logic!
Some more functions that edgestore provides
Replace file
You can replace an already uploaded file by passing the replaceTargetUrl
option. The old file will be automatically deleted after the upload.
const res = await edgestore.publicFiles.upload({
file,
options: {
replaceTargetUrl: oldFileUrl,
},
// ...
});
Temporary files
Edgestore provides us the option to store temporary files which if not confirmed are deleted within 24 hours.
To upload a temporary file simply add the following to your options
:
options: {
// ..
temporary: true,
},
To confirm a temporary file:
await edgestore.publicFiles.confirmUpload({
url: urlToConfirm,
});
Download files
Sometimes the browser displays the file instead of downloading it forcefully, if you want to force that download, use getDownloadUrl
:
import { getDownloadUrl } from "@edgestore/react/utils";
getDownloadUrl(
url, // the url of the file to download
"example.pdf" // optional, the name of the file to download
);
Conclusion
When it comes to getting your Next.js apps up and running quickly with file storage, Edgestore is a terrific solution. Many configuration choices covering a wide range of use-cases have been offered which make it super easy to use.
Edge Store's seamless integration with Next.js represents a significant step towards the development of web apps that are not only user-focused and user-friendly but also faster and more efficient. Its robust features and flexibility allow developers to handle complex file storage needs with ease, reducing development time and minimizing errors.
Read more and discover the full potential of Edge Store by visiting the official documentation. By leveraging Edge Store, you can enhance your Next.js applications and provide a superior experience for your users.
Related articles
Development using CodeParrot AI