How to upload PDFs in cloudinary with Next 15

While developing a side project for myself in Next 15, I found it rather difficult to upload pdfs in cloudinary. That’s why today i’ll be showing you how to upload pdfs in cloudinary with Next 15.
Before starting this you have to consider some restrictions that cloudinary has on uploading pdfs. One of them is the limit of maximum 10MB file size (assuming you’re using their free plan). Another is that cloudinary restricts the ability of new accounts to deliver pdfs and archive files like .zip to protect security and integrity of their customer accounts. You can read about it here. So, we’ll start by changing the setting to allow the delivery of pdfs. Now assuming you know about nextjs and cloudinary, let’s get right into it.
Changing the cloudinary settings
To allow the delivery of pdfs in cloudinary follow these steps:
Go to cloudinary and open your account settings.
Go to “Security” inside “Product environment settings”.
Check this option.
Setting up cloudinary
Now let’s install cloudinary using npm.
npm i cloudinary
Then go to the cloudinary console and setup this file anywhere in your project directory.
import { v2 as cloudinary } from "cloudinary";
cloudinary.config({
cloud_name: process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME,
api_key: process.env.NEXT_PUBLIC_CLOUDINARY_API_KEY,
api_secret: process.env.NEXT_PUBLIC_CLOUDINARY_API_SECRET,
});
export { cloudinary };
This will ensure we have a function which we can use anywhere in our project to access cloudinary.
Also, get these keys from the cloudinary console and add them in your .env file.
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME=add your cloudinary cloud name here
NEXT_PUBLIC_CLOUDINARY_API_KEY=add your cloudinary api key here
NEXT_PUBLIC_CLOUDINARY_API_SECRET=add your cloudinary api secret here
Setup API route
Now let’s setup our API route.
import { NextResponse } from "next/server"
import { cloudinary } from "@lib/cloudinary"
export async function POST(request) {
try {
const formData = await request.formData()
const file = formData.get("file")
if (!file) {
return NextResponse.json(
{ error: "File is required" },
{ status: 400 }
)
}
const fileBuffer = await file.arrayBuffer()
const mimetype = file.type
const filename = file.name
const encoding = "base64"
const dataOfBase64 = Buffer.from(fileBuffer).toString("base64")
const pdfUrl = "data:" + mimetype + ";" + encoding + "," + dataOfBase64
const result = await cloudinary.uploader.upload(
pdfUrl,
{
resource_type: "raw",
filename_override: filename,
folder: "pdfs",
}
)
console.log(result) //you can console log this uploadResult to see what is being uploaded to cloudinary
return NextResponse.json({
success: true,
message: "PDF uploaded successfully",
pdf: result.secure_url
})
} catch (error) {
console.error("Error uploading file:", error)
return NextResponse.json({ error: "Upload failed" }, { status: 500 })
}
}
Here, we get our file from the frontend through Formdata. To upload this file to cloudinary we have to change this file to a file path, a URL, or a readable stream. So we need to convert the File instance appropriately. This can be seen in the code from fileBuffer to result. Let’s understand this code:
File.arrayBuffer() reads the file as an ArrayBuffer which is the raw binary data of the file.
Then, we extract the metadata of the files and store them in mimetype and filename.
Then, we set the encoding to base64 which is the common format for encoding binary data into a text format which can be stored in URLs.
Then, we convert the file to base64. Buffer.from(fileBuffer) creates a Buffer object from the fileBuffer. This is then converted to base64-encoded string.
This then creates a pdfUrl that can then be safely uploaded to cloudinary.
Then, we upload this to cloudinary as seen in the result. We can then create a simple frontend like this to integrate the API route.
"use client";
import { useState } from "react";
export default function UploadPDF() {
const [file, setFile] = useState(null);
const [message, setMessage] = useState("");
const handleFileChange = (e) => {
setFile(e.target.files[0]);
};
const handleUpload = async (e) => {
e.preventDefault();
if (!file) return;
const formData = new FormData();
formData.append("file", file);
const res = await fetch("/api/upload", {
method: "POST",
body: formData,
});
const data = await res.json();
setMessage(data.message || "Upload failed");
};
return (
<div>
<h2>Upload PDF</h2>
<form onSubmit={handleUpload}>
<input type="file" accept="application/pdf" onChange={handleFileChange} />
<button type="submit">Upload</button>
</form>
<p>{message}</p>
</div>
);
}
This is how we can upload PDFs to cloudinary with Next 15. Thank you for taking the time to read this post. I hope this helped you. Do let me know if you struggle with any of this or have any feedback.
Subscribe to my newsletter
Read articles from Swikar Neupane directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Swikar Neupane
Swikar Neupane
I am a frontend focused fullstack developer with expertise in React and Next. I also have a brief experience as a graphic designer. I love experimenting with and learning new tech stuffs be it technologies or coding practices.