Skip to content

How to Convert Documents to Images

Document processors like Microsoft Office are the de facto standard for producing and formatting documents. When transmitting information such as statements or invoices, even its most passionate customers seek extra features and usefulness from online file converters to make PDFs. The reason for this is that word documents can be edited, whereas PDF documents cannot. The same may be said about how PDF documents maintain their formatting across numerous devices. In this article, you will be able to create a feature that distinguishes pdf pages as images and provide online storage for any page a user requires i.e for future reference.

Lets’ begin writing

Check the sandbox demo on Codesandbox.

You can also get the project github repo using Github.

Entry-level javascript and React/Nextjs knowledge.

Create your new Nextjs app using npx create-next-app pdfconvert in your terminal. Head to your project root directory cd pdfconvert

In our Nextjs framework backend, we will have to integrate Cloudinary, which will be used to store our uploaded processed images.

Create your Cloudinary account using Link and log into it to access your dashboard which contains your environment variable keys necessary for the integration in your project.

In your project directory, include Cloudinary in your dependencies npm install cloudinary

Use the guide below to fill in your environment variables in the .env.local file from the Cloudinary dashboard.

CLOUDINARY_CLOUD_NAME =

CLOUDINARY_API_KEY =

CLOUDINARY_API_SECRET =

Restart your project using npm run dev.

In the pages/api folder, create a new file named upload.js. Start by configuring the environment keys and libraries.

var cloudinary = require("cloudinary").v2;

cloudinary.config({
    cloud_name: process.env.CLOUDINARY_NAME,
    api_key: process.env.CLOUDINARY_API_KEY,
    api_secret: process.env.CLOUDINARY_API_SECRET,
});

Create a handler function to execute the POST request. The function will receive media file data and post it to the cloudinary website. It then captures the media file’s cloudinary link and sends it back as a response.

export default async function handler(req, res) {
    if (req.method === "POST") {
        let url = ""
        try {
            let fileStr = req.body.data;
            const uploadedResponse = await cloudinary.uploader.upload_large(
                fileStr,
                {
                    resource_type: "video",
                    chunk_size: 6000000,
                }
            );
            url = uploadedResponse.url
        } catch (error) {
            res.status(500).json({ error: "Something wrong" });
        }

        res.status(200).json({data: url});
    }
}

The code above concludes our backend.

Before you begin the front end, include the following in your environment variables: npm install pdfjs-dist

Create a directory, components/Converter.client.js, and include it in your pages/index directory.

"pages/index"

import Converter from "../components/Converter.client";

export default function Home() {
  return (
    <Converter />
  );
}

In the components/Converter.client.js directory, start with including the necessary imports

"components/Converter.client.js"


import React, { useState, useRef, useEffect } from "react";

import * as pdfjsLib from "pdfjs-dist/build/pdf";
pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.js`;

const HTTP_SUCCESS = 200;

The HTTP_SUCCESS variablewill be used to determine successful responses from api calls.

Create a function named Converter and declare the following statehooks:

"components/Converter.client.js"

export default function Converter() {
    const [img, setImg] = useState();
    const [name, setName] = useState("");
    const [selectedFile, setSelectedFile] = useState(null);
    const [pages, setPages] = useState(0);
    const [currentPage, setCurrentPage] = useState(1);
    const [pdfFile, setPdfFile] = useState(null);
    const pageRenderRef = useRef();

    return (
        <>
        works
        </>
    )
}

useState is a hook that lets you add React state to function components and the useRef hook allows you to persist values between renders. We will also add a useEffect hook to perform side effects in our functional component.

useEffect(() => {
    if (pdfFile && currentPage) {
      pageRender();
    }
  }, [pdfFile, currentPage]);

The above hook will lookout for the pdf file and currentPage and render the page whenever changes are made in the two variables.

Create a function convert :

  const onConvert = async () => {
    const uri = URL.createObjectURL(selectedFile);

    const pdf = await pdfjsLib.getDocument({ url: uri });

    await pdf.promise.then(
      (_pdf) => {
        const {
          _pdfInfo: { numPages },
        } = _pdf;
        setPages(numPages);
        setPdfFile(_pdf);
      },
      (error) => {
        console.log("PDF error :", error);
      }
    );
  };

The function above starts by creating a URL string object from the file object selectedFile, assigning it to the constant uri. The constant pdf will use pdfjsLib to capture the uri string and categorize it based on the files selected and number of pages the file contains using react useState hooks.

Create a pageRender function to capture the user’s selected page to a canvas and assign it to the setImg hook as a string object

const pageRender = () => {
    pdfFile.getPage(currentPage).then((page) => {
      {
        const viewport = page.getViewport({ scale: 1 });
        const canvas = pageRenderRef.current;
        const context = pageRenderRef.current.getContext("2d");
        canvas.height = viewport.height;
        canvas.width = viewport.width;
        const renderContext = {
          canvasContext: context,
          viewport: viewport,
          enableWebGL: false,
        };
        page.render(renderContext);
        setImg(canvas.toDataURL());
        console.log(pageRenderRef.current);
      }
    });
};

Once the image is captured, we will have to upload it to the backend for cloudinary upload. Note the HTTP_SUCCESS variable created earlier.

  const uploadVideo = async () => {
    console.log(img);
    try {
      fetch("/api/upload", {
        method: "POST",
        body: JSON.stringify({ data: img }),
        headers: { "Content-Type": "application/json" },
      }).then((response) => {
        console.log("Backend http status code : ", response.status);
        if (response.status === HTTP_SUCCESS) {
          response.json().then((result) => {
            console.log(result);
          });
        }
      });
    } catch (error) {
      console.error(error);
    }
};

Finally, include the following in your return statement to create your UI. The css files can be located in the Github repository

return (
    <div className="container">
      <h1>Conversion of Documents to Images with Nextjs</h1>
      <div className="row">
        <div className="column">
          <input
            type="file"
            accept="application/pdf"
            onChange={(e) => setSelectedFile(e.target.files[0])}
          />
          {selectedFile ? <h3>You have selected: {selectedFile.name}</h3> : ""}
          {selectedFile && <button onClick={onConvert}>Convert</button>}
        </div>
        <div className="column">
          {pdfFile && (
            <>
              <input
                type="number"
                placeholder="Page number"
                value={currentPage}
                onChange={(e) => setCurrentPage(parseInt(e.target.value))}
                min="1"
                max={pages}
              />{' '}
              <button onClick={uploadVideo}>Upload Image</button><br /><br />
              <canvas ref={pageRenderRef} width="100" height="200"></canvas>
            </>
          )}


        </div>
      </div>
    </div>
);

The UI should look like below

|UI

Thats it! Ensure to go through the article to enjoy the experience.

Back to top

Featured Post