DEV Community

Cover image for Building a Fast and Efficient Image Converter with Next.js, Sharp and React
Florian Zeba
Florian Zeba

Posted on • Originally published at fzeba.com

Building a Fast and Efficient Image Converter with Next.js, Sharp and React

In today's digital landscape, the need to convert images between various formats is commonplace.
To address this, I developed an Image Converter Tool that streamlines the process, allowing users to effortlessly transform images into formats like JPG, PNG, WebP, and PDF.
This blog post delves into the technical architecture of the application, highlighting key components and code implementations.

Application Overview

The Image Converter Tool is a web-based application built using Next.js, React, and TypeScript.
It provides a user-friendly interface for uploading images and converting them to the desired format.
The backend leverages the sharp library for image processing and jspdf for PDF generation.

Frontend Implementation

The frontend is structured around a React functional component that manages the user interface and handles user interactions.
The primary component, WebPConverter, is defined in app/page.tsx.

State Management

State is managed using React's useState hook to track the selected file, conversion format, conversion status, and the resulting converted file URL.

const [file, setFile] = (useState < File) | (null > null);
const [convertedFile, setConvertedFile] = (useState < string) | (null > null);
const [format, setFormat] = useState('jpg');
const [isConverting, setIsConverting] = useState(false);
Enter fullscreen mode Exit fullscreen mode

File Selection

The handleFileChange function updates the file state when a user selects a file, and resets the convertedFile state to null to clear any previous results.

const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  const selectedFile = e.target.files?.[0];
  if (selectedFile) {
    setFile(selectedFile);
    setConvertedFile(null);
  }
};
Enter fullscreen mode Exit fullscreen mode

Format Selection

The Select component from the UI library allows users to choose the desired output format.
The onValueChange prop updates the format state accordingly.

<Select onValueChange={setFormat} defaultValue={format}>
  <SelectTrigger>
    <SelectValue placeholder='Select format' />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value='jpg'>JPG</SelectItem>
    <SelectItem value='png'>PNG</SelectItem>
    <SelectItem value='webp'>WebP</SelectItem>
    <SelectItem value='pdf'>PDF</SelectItem>
  </SelectContent>
</Select>
Enter fullscreen mode Exit fullscreen mode

Conversion Process

Upon clicking the "Convert" button, the handleConversion function is invoked.
This function performs the following steps:

  1. FormData Creation: A FormData object is created, appending the selected file and desired format.

  2. API Request: An asynchronous POST request is sent to the /api/convert endpoint with the FormData payload.

  3. Response Handling: The response is processed into a blob, and a URL is generated using URL.createObjectURL.
    This URL is then set in the convertedFile state for user access.

const handleConversion = async () => {
  if (!file) return;
  setIsConverting(true);

  try {
    const formData = new FormData();
    formData.append('file', file);
    formData.append('format', format);

    const response = await fetch('/api/convert', {
      method: 'POST',
      body: formData,
    });

    const blob = await response.blob();
    const url = URL.createObjectURL(blob);
    setConvertedFile(url);
  } catch (error) {
    console.error('Conversion failed:', error);
  } finally {
    setIsConverting(false);
  }
};
Enter fullscreen mode Exit fullscreen mode

Backend Implementation

The backend is responsible for processing the image conversion requests.
The POST function in the API route handles the incoming requests.

Request Handling

The function begins by parsing the incoming FormData to extract the file and desired format.

const formData = await request.formData();
const file = formData.get('file') as File;
const format = formData.get('format') as string;
Enter fullscreen mode Exit fullscreen mode

Buffer Conversion

The uploaded file is converted into an ArrayBuffer and then into a Buffer for processing with sharp.

const bytes = await file.arrayBuffer();
const buffer = Buffer.from(bytes);
Enter fullscreen mode Exit fullscreen mode

Format Validation

A helper function, isValidImageFormat, checks if the requested format is among the supported image formats (jpg, png, webp).

function isValidImageFormat(format: string): format is ImageFormat {
  return ['jpg', 'png', 'webp'].includes(format);
}
Enter fullscreen mode Exit fullscreen mode

Image Conversion

Depending on the desired output format, the function processes the image accordingly:

  • PDF Conversion: If the target format is PDF, the image is first converted to PNG using sharp. Then, jspdf is used to create a PDF with the image embedded.
if (format === 'pdf') {
  const pngBuffer = await sharp(buffer).png().toBuffer();
  const metadata = await sharp(pngBuffer).metadata();
  const { width = 595, height = 842 } = metadata;

  const doc = new jsPDF({
    orientation: width > height ? 'landscape' : 'portrait',
    unit: 'px',
    format: [width, height],
  });

  const imageData = `data:image/png;base64,${pngBuffer.toString('base64')}`;
  doc.addImage(imageData, 'PNG', 0, 0, width, height);

  const outputBuffer = Buffer.from(doc.output('arraybuffer'));

  return new NextResponse(outputBuffer, {
    headers: {
      'Content-Type': 'application/pdf',
      'Content-Disposition': 'attachment; filename="converted.pdf"',
    },
  });
}
Enter fullscreen mode Exit fullscreen mode

TL;DR

  • The Image Converter Tool is a web application built with Next.js and React that allows users to convert images between various formats.
  • The frontend provides an intuitive interface for uploading images and selecting the desired output format.
  • The backend leverages sharp for image processing and jspdf for PDF generation.
  • By combining these technologies, the application delivers a seamless image conversion experience.

Link to webtool: https://image-converter-tool.vercel.app/
Link to repo: https://github.com/flnzba/image-converter-tool

Read this article and more on fzeba.com.

Top comments (0)