Upload User Images via API in a Next.js App with CKEditor 5
In today's digital age, images play a crucial role in enhancing the user experience on websites. With the rise of headless content management systems (CMS) and modern front-end frameworks, developers are increasingly relying on APIs to handle various functionalities, including image uploads. This article explores how to upload user images via API in a Next.js app with CKEditor 5.
Why Use an API for Image Uploads?
Using an API for image uploads offers several benefits. First, it allows for better scalability and performance, as the image processing and storage can be handled by specialized services. Additionally, it enables developers to implement a consistent and standardized approach for handling media assets across different applications and platforms. Furthermore, it enhances security, as images can be uploaded and stored without exposing sensitive server-side resources.
CKEditor 5 and Image Uploads
CKEditor 5 is a popular open-source rich text editor that offers a wide range of features and customization options. By default, CKEditor 5 supports image uploads via its built-in file upload functionality. However, in a headless CMS or serverless architecture, this functionality may not be suitable, as it typically relies on server-side resources to handle the file uploads. To overcome this limitation, developers can use an API to handle image uploads instead.
Setting Up the Next.js App and CKEditor 5
To get started, developers will need to set up a new Next.js app and install CKEditor 5 as a dependency. This can be done using the following commands:
npx create-next-app my-app
cd my-app
npm install @ckeditor/ckeditor5-react @ckeditor/ckeditor5-build-classic
Once installed, developers can import CKEditor 5 into their Next.js app and use it as follows:
import React from 'react';
import CKEditor from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
function MyEditor() {
return (
<CKEditor
editor={ClassicEditor}
data="Hello, world!
"
onReady={editor => {
console.log('Editor is ready to use!', editor);
}}
onChange={(event, editor) => {
const data = editor.getData();
console.log({ event, editor, data });
}}
onBlur={(event, editor) => {
console.log('Blur.', editor);
}}
onFocus={(event, editor) => {
console.log('Focus.', editor);
}}
/>
);
}
export default MyEditor;
Integrating the API for Image Uploads
To integrate the API for image uploads, developers can use a popular service like Cloudinary or AWS S3. These services offer a simple and secure way to store and manage media assets, and typically provide APIs or SDKs for uploading files. For this example, we will use Cloudinary.
To set up Cloudinary, developers will need to sign up for an account and create a new API key and secret. Once they have these, they can use the Cloudinary Node.js SDK to handle the image uploads. Here's an example of how to use the Cloudinary Node.js SDK to handle image uploads in a Next.js API route:
import cloudinary from 'cloudinary';
cloudinary.config({
cloud_name: 'YOUR\_CLOUD\_NAME',
api\_key: 'YOUR\_API\_KEY',
api\_secret: 'YOUR\_API\_SECRET',
});
export default async (req, res) => {
if (req.method === 'POST') {
const file = req.files.file;
const uploadResult = await cloudinary.v2.uploader.upload(file.path);
return res.status(200).json({
url: uploadResult.secure\_url,
});
}
return res.status(405).json({ message: 'Method not allowed' });
};
Once the API route is set up, developers can modify the CKEditor 5 configuration to use the API for image uploads. Here's an example of how to do this:
import React, { useState } from 'react';
import CKEditor from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
function MyEditor() {
const [uploadUrl, setUploadUrl] = useState('');
const onUpload = async (file) => {
const formData = new FormData();
formData.append('file', file);
const res = await fetch('/api/upload', {
method: 'POST',
body: formData,
});
const data = await res.json();
setUploadUrl(data.url);
};
return (
<CKEditor
editor={ClassicEditor}
data="Hello, world!
"
upload={(file) => {
onUpload(file);
}}
onReady={(editor) => {
editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
return {
upload: () => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('POST', uploadUrl, true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.upload.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
const json = JSON.parse(xhr.responseText);
if (json.error) {
reject(json.error);
} else {
resolve({
default: json.url,
});
}
} else {
reject(xhr.statusText);
}
};
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
const json = JSON.parse(xhr.responseText);
if (json.error) {
reject(json.error);
} else {
resolve({
default: json.url,
});
}
} else {
reject(xhr.statusText);
}
};
xhr.onerror = () => {
reject('Image upload failed due to a network error.');
};
xhr.ontimeout = () => {
reject('Image upload failed due to a timeout.');
};
loader.file.then((file) => {
const reader = new FileReader();
reader.onload = () => {
const body = new FormData();
body.append('file', file);
xhr.send(body);
};
reader.readAsArrayBuffer(file);
});
});
}}
onChange={(event, editor) => {
const data = editor.getData();
console.log({ event, editor, data });
}}
onBlur={(event, editor) => {
console.log('Blur.', editor);
}}
onFocus={(event, editor) => {
console.log('Focus.', editor);
}}
/>
);
}
export default MyEditor;
In this article, we explored how to upload user images via API in a Next.js app with CKEditor 5. We covered the benefits of using an API for image uploads, and how to integrate the API with CKEditor 5. By using an API for image uploads, developers can improve scalability, performance, security, and consistency in their applications. With the power of Next.js and CKEditor 5, developers can create rich and engaging user experiences with ease.