Front-End Development Building an Image Upload Feature with JavaScript Mastering Image Alignment: Centering Images with HTML & CSS Adding Video to Your React Native App with react-native-video HTML Image Slider: Do It Yourself and 1-Step Image Gallery Widget How to Effectively Manage Digital Assets in a PHP Image Gallery Introducing Angular Image Editor: Your New Editing Too Mastering Javascript Image Annotation Mastering JavaScript Image Popup Python Video Player: 3 Free Options and a Quick Tutorial Image Recognition Machine Learning: Use Cases and Common Algorithms HTML/CSS: How to Center Images Vertically and Horizontally How to Create an Image Map Understand CSS Background Position with 4 Simple Examples Java for Image Processing: 4 Libraries You Should Know Python Video Processing: 6 Useful Libraries and a Quick Tutorial Blur Image CSS: Two Ways to Blur Images for Gorgeous Effects Designing a Video Flipping App for Android Build an App for Embedding Video Watermarks on Android Devices Change Image on Hover with HTML and CSS How to Align Images with CSS Full Page Background Image with CSS: Tutorial and 5 Automation Tips Using CSS to Scale Page Elements and a Better Way to Scale Your Images CSS Background Image: Quick Tutorial and 3 Automation Tips Featured Image: Best Practices to Feature Images on Your Website Image Gallery Websites: Tips and Tricks for a Stunning Image Gallery 6 Ways to Stretch a Background Image with CSS Auto Cropping for Images and Video: Features & Best Practices FLAC vs. WAV: 4 Key Differences and How to Choose Converting Audio to Video: A Practical Guide FLAC vs. AIFF: 5 Key Differences and How to Choose FLAC vs. MQA: 5 Key Differences and How to Choose Converting WAV Files To OGG The Ultimate Guide On Converting OGG Files To WAV Sound Choices: FLAC vs. MP3 AAC vs MP3 – The Future of Audio Files All about AIFF and how it compares to WAV and MP3 Integrating Cloudinary with Netlify Integrating Cloudinary with Svelte and SvelteKit Integrating Cloudinary with Nuxt Integrating Cloudinary with Gatsby File Upload as a Service: How It Works and 5 Leading Solutions Native Mobile App Development Creative Uses for CSS Inner Border and 3 Ways to Set a Border Integrating Cloudinary with Next.js Front-End Development: The Complete Guide

Building an Image Upload Feature with JavaScript

js image uploading

Uploading image assets to a web application is common in today’s digital world. But as a developer, how do you even implement this feature into your applications?

In this tutorial, we’ll build a simple image uploader that allows users to upload images into a web app. Are you excited to learn? Let’s get started!

Join thousands of businesses transforming their digital asset management with Cloudinary. Sign up for free today!

js image uploading

Uploading an Image Using The File API

The File API is a Web API that enables web applications to access files and their contents. Developers can implement this feature in two ways:

  1. An input element with a type="file" to let the user choose one or more files from their device storage.
  2. Using the HTML Drag and Drop API to allow users to upload files to a web application.

In the steps to follow, we’ll explain how to implement a simple image uploader in HTML, CSS, and JavaScript.

Step 1 – HTML and CSS Structure

First, let’s create the structure of what the web page we’ll use in this example will look like. Create a file named index.html and add the following code to it:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Javascript Image Upload</title>
    <link rel="stylesheet" href="index.css">
</head>
<body>
    <div class="container">
        <input type="file" id="fileUpload" accept="image/*">
    </div>
  <div class="image-container">
    <img id="output" src="" alt="">
  </div>
</body>
<script src="index.js"></script>
</html>

Next, create another file named index.css and add the following code to it:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    flex-direction: column;
    background-color: white;
    font-family: Arial, sans-serif;
}

.container {
    display: flex;
    justify-content: center;
    align-items: center;
    border: 2px solid #ccc;
    padding: 20px;
    margin-bottom: 30px;
    border-radius: 10px;
    background-color: #f9f9f9;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

#fileUpload {
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
    cursor: pointer;
}

Here’s what’s going on in the two blocks of code above.

  • The HTML code defines the structure of the page.
  • The HTML also includes a link to an external index.css for styling and an index.js file which will handle the functionality for image uploading and displaying, which we will create in a moment.

Here’s what the result looks like in the browser:

js image uploading

Step 2 – Handle Image Upload Using JavaScript

In the same folder with the previous HTML and CSS files, create another file named index.js and add the following code to it:

const fileInput = document.getElementById("fileUpload")
const imageOutput = document.getElementById("output");

fileInput.addEventListener("change", async () => {
    let [file] = fileInput.files

    const reader = new FileReader();
    reader.onload = (e) => {
      imageOutput.src = e.target.result;
    };

    reader.onerror = (err) => {
        console.error("Error reading file:", err);
        alert("An error occurred while reading the file.");
    };


    reader.readAsDataURL(file);
})

Let’s break down what’s going on in that code block:

  • The first part of the code selects the input and img elements using their respective IDs.
  • Next, we added an event listener to the fileInput element to listen for the “change” event, which triggers when a user selects a file.
  • Finally, when a file is selected, a FileReader object reads the file as a Data URL. Once the file is read, the img element src attribute is set to the resulting Data URL, displaying the selected image.

Specify Acceptable File Types for Upload

We can specify the acceptable file types the input element should accept using the accept attribute. The value is a comma-separated list of allowed file extensions or MIME types. For example, accept="image/png, image/jpeg" or accept=".png, .jpg, .jpeg" accept PNG or JPEG files. We can also use a wildcard to accept any type of image file extension, as shown below:

<input type="file" id="fileUpload" accept="image/*">

Accepting multiple files

By default, a user can only upload a single file. However, we can use the multiple Boolean attribute to allow users to upload more than one file at a time.

<input type="file" id="fileUpload" multiple>

Upload an Image Using Drag and Drop

The HTML drag-and-drop interface allows web apps to implement drag-and-drop through the following two steps:

  • Specify a target element for the file drop, also known as the “drop zone”.
  • Specify event handlers for the “drop” and “dragover” events.

Let’s see how to do this in the series of steps below.

Step 1 – HTML and CSS Structure

Open the index.html file and replace its contents with the following:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Drag and drop image upload</title>
    <link rel="stylesheet" href="index.css">
</head>
<body>
    <div class="container">
        <div class="drag-drop-area" id="dragDropArea">
            <p>Drag & Drop your files here</p>
        </div>
        <div id="output"></div>
    </div>
    <script src="script.js"></script>
</body>
</html>

Then, in the index.css file, replace the code with the following:

body {
    font-family: Arial, sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
}

.container {
    text-align: center;
}

.drag-drop-area {
    border: 2px dashed #ccc;
    padding: 20px;
    border-radius: 10px;
    background-color: white;
    cursor: pointer;
    width: 300px;
    margin: 20px auto;
    position: relative;
}

.drag-drop-area p {
    margin: 10px 0;
}

#fileInput {
    display: none;
}

#output {
    margin-top: 20px;
}

#output img {
    max-width: 100%;
    height: auto;
}

Here’s what the webpage looks like:

js image uploading

Step 2 – Add JavaScript

In the index.js file, replace the code with the following:

const dragDropArea = document.getElementById("dragDropArea");
const output = document.getElementById("output");

// Step 1 - Add an event listener for the dragover event
dragDropArea.addEventListener("dragover", (e) => {
    e.preventDefault();  // This turns off the browser's default drag and drop handler.
    dragDropArea.classList.add("dragover");
});

// Step 2 - Add an event listener for the drop event
dragDropArea.addEventListener("drop", (e) => {
    e.preventDefault();
    dragDropArea.classList.remove("dragover");

    const files = e.dataTransfer.files;
    if (files.length === 0) {
        alert("No files selected.");
        return;
    }
    output.innerHTML = "";

    for (const file of files) {
        if (!file.type.startsWith("image/")) {
            alert("Only image files are allowed.");
            return;
        }
        const reader = new FileReader();
        reader.onload = (e) => {
            const img = document.createElement("img");
            img.src = e.target.result;
            output.appendChild(img);
        };
        reader.onerror = (err) => {
            console.error("Error reading file:", err);
            alert("An error occurred while reading the file.");
        };
        reader.readAsDataURL(file);
    }
});

Again, let’s break down the logic behind the code:

  • The first part of the code selects two HTML elements: the drag-drop area and an output area.
  • Next, we create event handlers to handle the “drop” and “dragover” events.
  • We also use the DataTransfer object (in e.dataTransfer.files) to access the data being dragged during the drag-and-drop operation.
  • Then, we process the dropped files using the FileReader method and create an img element to display the uploaded image file.

Wrapping Up

In this article, we explored two methods of uploading image files in a web application using HTML, CSS, and JavaScript: the traditional file input approach and the interactive drag-and-drop method. While several libraries simplify the process, knowing how to write the code on your own will allow you to gain deeper insights into browser APIs and improve your overall web app development skills.

Empower your development team with Cloudinary’s easy-to-use APIs and SDKs. Sign up for free today!

QUICK TIPS
Colby Fayock
Cloudinary Logo Colby Fayock

In my experience, here are tips that can help you better implement and optimize an image upload feature with JavaScript:

  1. Validate file size before upload
    Implement client-side validation to check the file size before initiating the upload. This prevents users from uploading excessively large files, which can slow down the server and degrade user experience. You can set a maximum file size and display an error message if the file exceeds this limit.
  2. Compress images before upload
    Use JavaScript libraries like compress.js or pica to compress images client-side before they are uploaded. This reduces the file size without sacrificing too much quality, resulting in faster uploads and reduced server load.
  3. Use async/await for file processing
    When handling file uploads, especially if performing additional processing like compression or format conversion, use async/await to manage asynchronous operations. This makes your code more readable and easier to debug.
  4. Implement a progress indicator
    Provide users with feedback during the upload process by implementing a progress bar. This enhances the user experience by visually indicating how much of the file has been uploaded, especially for large files.
  5. Secure file uploads against XSS
    Always sanitize file names and validate file types server-side to prevent malicious files from being uploaded. Avoid relying solely on client-side validation, as it can be bypassed by attackers.
  6. Support multiple image formats
    Consider supporting modern image formats like WebP, AVIF, or JPEG XL in addition to traditional formats (JPEG, PNG). This ensures that your application can handle various image types efficiently, especially with regard to file size and quality.
  7. Implement drag-and-drop fallback
    For users with devices or browsers that do not fully support the drag-and-drop API, provide a fallback to the standard file input method. This ensures that all users can upload images, regardless of their environment.
  8. Optimize server-side image handling
    Once images are uploaded, optimize them server-side using tools like ImageMagick or Sharp. This ensures that images are properly resized, compressed, and converted to suitable formats before being stored or served.
  9. Enable chunked file uploads for large images
    For large images or poor network conditions, implement chunked file uploads. This technique splits a large file into smaller parts, uploads each part separately, and reassembles them server-side. This improves reliability and allows resuming uploads if interrupted.
  10. Implement image caching strategies
    Once images are uploaded and optimized, use a content delivery network (CDN) to cache and serve images efficiently. Implementing caching headers ensures that frequently accessed images are delivered quickly without repeatedly hitting your servers.
Last updated: Aug 24, 2024