Last updated: February 5, 2025

<span aria-hidden="true" id="implementing-file-uploads-with-bootstrap-5"></span>

# Implementing file uploads with Bootstrap 5

![Tim Koschützki](/assets/images/teammates/avatar-tim-kos-1.jpg?dpl=dpl_9etF2BeBrsRRWnkZRYTyEp7mxrwF)

**Tim Koschützki**

Co-founder · Berlin, Germany · Show bio

[](https://x.com/tim%5Fkos)[](https://github.com/tim-kos)

File uploads are essential in modern web applications. Bootstrap 5 provides tools to create sleek and user-friendly file upload interfaces. This guide will walk you through implementing file uploads using Bootstrap 5, including drag-and-drop functionality, custom upload buttons, and AJAX progress indication.

<span aria-hidden="true" id="introduction-to-bootstrap-5-file-uploads"></span>

## Introduction to Bootstrap 5 file uploads

Bootstrap 5 offers a variety of components for building responsive web interfaces. While it doesn't provide a dedicated file upload component, you can use Bootstrap's form controls to create custom file upload forms that integrate seamlessly into your application.

In this tutorial, we'll cover:

* Setting up a Bootstrap 5 environment
* Creating a simple file upload form
* Enhancing it with drag-and-drop functionality
* Uploading with AJAX and progress indication
* Handling file uploads on the server side
* Implementing security best practices and error handling

<span aria-hidden="true" id="setting-up-a-bootstrap-5-environment"></span>

## Setting up a Bootstrap 5 environment

To get started, set up a basic Bootstrap 5 environment. You can include Bootstrap via CDN or install it locally.

**Including via CDN:**

Add the following links to your HTML file's `<head>` section:

```html
<link
  href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
  rel="stylesheet"
  integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
  crossorigin="anonymous"
/>
<script
  src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
  integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
  crossorigin="anonymous"
></script>

```

**Including via NPM:**

If you're using a build tool, install Bootstrap via NPM:

```bash
npm install bootstrap@5.3.3

```

<span aria-hidden="true" id="creating-a-simple-file-upload-form"></span>

## Creating a simple file upload form

Let's create a basic file upload form using Bootstrap's form controls:

```html
<form action="/upload" method="post" enctype="multipart/form-data">
  <div class="mb-3">
    <label for="formFile" class="form-label">Choose a file to upload</label>
    <input
      class="form-control"
      type="file"
      id="formFile"
      name="file"
      accept="image/jpeg,image/png,application/pdf"
    />
  </div>
  <div class="progress d-none mb-3">
    <div class="progress-bar" role="progressbar" style="width: 0%"></div>
  </div>
  <button type="submit" class="btn btn-primary">Upload</button>
</form>

```

<span aria-hidden="true" id="enhancing-with-drag-and-drop-functionality"></span>

## Enhancing with drag-and-drop functionality

Implement drag-and-drop functionality with proper validation and error handling:

```html
<div class="mb-3">
  <label for="formFile" class="form-label">Upload your file</label>
  <div id="dropZone" class="rounded border border-primary p-4 text-center">
    Drag and drop a file here or click to select
  </div>
  <div id="errorMessage" class="alert alert-danger d-none mt-2"></div>
  <input
    type="file"
    id="formFile"
    name="file"
    class="d-none"
    accept="image/jpeg,image/png,application/pdf"
  />
</div>

<script>
  const dropZone = document.getElementById('dropZone')
  const formFile = document.getElementById('formFile')
  const errorMessage = document.getElementById('errorMessage')

  const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf']
  const maxSize = 5 * 1024 * 1024 // 5MB

  function validateFile(file) {
    if (!allowedTypes.includes(file.type)) {
      throw new Error('Invalid file type. Please upload JPEG, PNG or PDF files.')
    }
    if (file.size > maxSize) {
      throw new Error('File too large. Maximum size is 5MB.')
    }
  }

  function showError(message) {
    errorMessage.textContent = message
    errorMessage.classList.remove('d-none')
  }

  function hideError() {
    errorMessage.classList.add('d-none')
  }

  dropZone.addEventListener('click', () => formFile.click())

  dropZone.addEventListener('dragover', (e) => {
    e.preventDefault()
    dropZone.classList.add('bg-light')
  })

  dropZone.addEventListener('dragleave', () => {
    dropZone.classList.remove('bg-light')
  })

  dropZone.addEventListener('drop', (e) => {
    e.preventDefault()
    dropZone.classList.remove('bg-light')
    hideError()

    try {
      const file = e.dataTransfer.files[0]
      validateFile(file)
      formFile.files = e.dataTransfer.files
      updateDropZoneText()
    } catch (error) {
      showError(error.message)
    }
  })

  formFile.addEventListener('change', () => {
    hideError()
    try {
      if (formFile.files.length > 0) {
        validateFile(formFile.files[0])
        updateDropZoneText()
      }
    } catch (error) {
      showError(error.message)
      formFile.value = ''
    }
  })

  function updateDropZoneText() {
    dropZone.textContent =
      formFile.files.length > 0
        ? formFile.files[0].name
        : 'Drag and drop a file here or click to select'
  }
</script>

```

<span aria-hidden="true" id="handling-file-uploads-on-the-server-side"></span>

## Handling file uploads on the server side

Implement secure file handling with Express and Multer:

```javascript
const express = require('express')
const multer = require('multer')
const path = require('path')

const app = express()

const storage = multer.diskStorage({
  destination: 'uploads/',
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9)
    cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname))
  },
})

const fileFilter = (req, file, cb) => {
  const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf']
  if (!allowedTypes.includes(file.mimetype)) {
    cb(new Error('Invalid file type'), false)
    return
  }
  cb(null, true)
}

const upload = multer({
  storage: storage,
  fileFilter: fileFilter,
  limits: {
    fileSize: 5 * 1024 * 1024, // 5MB
  },
})

app.post('/upload', upload.single('file'), (req, res) => {
  if (!req.file) {
    return res.status(400).json({ error: 'No file uploaded.' })
  }
  res.json({ message: 'File uploaded successfully', file: req.file })
})

app.use((error, req, res, next) => {
  if (error instanceof multer.MulterError) {
    return res.status(400).json({ error: 'File upload error: ' + error.message })
  }
  next(error)
})

app.listen(3000, () => {
  console.log('Server started on http://localhost:3000')
})

```

<span aria-hidden="true" id="uploading-with-ajax-and-progress-indication"></span>

## Uploading with Ajax and progress indication

For improved user experience, you can upload files asynchronously and provide real-time feedback on the upload progress. The following example demonstrates how to intercept a form submission, send the file via XMLHttpRequest, and update a Bootstrap progress bar in real time:

```javascript
const form = document.querySelector('form')
const progressBarEl = document.querySelector('.progress')
const progressFill = document.querySelector('.progress-bar')

form.addEventListener('submit', (e) => {
  e.preventDefault()
  const formData = new FormData(form)
  const xhr = new XMLHttpRequest()

  xhr.open('POST', form.getAttribute('action'), true)

  xhr.upload.addEventListener('progress', (event) => {
    if (event.lengthComputable) {
      const percentage = (event.loaded / event.total) * 100
      progressFill.style.width = percentage + '%'
      progressFill.textContent = Math.round(percentage) + '%'
      progressBarEl.classList.remove('d-none')
    }
  })

  xhr.onload = () => {
    if (xhr.status === 200) {
      alert('File uploaded successfully')
    } else {
      alert('File upload failed')
    }
    progressBarEl.classList.add('d-none')
    progressFill.style.width = '0%'
    progressFill.textContent = ''
  }

  xhr.onerror = () => {
    alert('Upload error')
    progressBarEl.classList.add('d-none')
    progressFill.style.width = '0%'
    progressFill.textContent = ''
  }

  xhr.send(formData)
})

```

<span aria-hidden="true" id="security-considerations"></span>

## Security considerations

When implementing file uploads, consider these security measures:

* Validate file types on both client and server side
* Implement file size limits
* Use secure file storage locations
* Implement rate limiting for uploads to prevent abuse
* Scan uploaded files for malware
* Use CSRF protection
* Implement proper error handling, including error logging for security monitoring

<span aria-hidden="true" id="conclusion"></span>

## Conclusion

By combining Bootstrap 5 with robust file upload techniques and proper security measures, you can create a seamless and user-friendly file upload system. The implementation includes drag-and-drop functionality, AJAX-based progress indication, and comprehensive error handling.

For a production-ready solution that handles file uploads and processing at scale, consider[Transloadit](/index.md). Transloadit offers reliable file uploading and encoding services that can streamline your development process and handle complex file processing tasks.

\#bootstrap#bootstrap-5#file-upload#drag-and-drop#file-upload-button#handling-uploads-service

### 👩‍💻 Join 20k+ developers

Sign up for our [monthly newsletter](/newsletters.md) to receive direct links to 3 exclusive tech — and 2 product updates. No less, no more.

Your email:

Get access

## File uploading and encoding. Made simple.

Transloadit streamlines file handling for developers, trusted by brands like Coursera and The New York Times. We’re known for a reliable API, top-notch support, and a strong commitment to open source, with projects like [Uppy⁠](https://uppy.io) and [Tus⁠](https://tus.io) setting standards in file processing.

[Sign up](/c/)[Book a Demo](https://survey.typeform.com/to/kRg47Xi5)

No credit card needed

Cancel anytime
