Home/Blog/How to upload files in HTML: Complete developer guide

How to upload files in HTML: Complete developer guide

It is pretty common for websites or apps to allow users to upload files as a feature or part of a feature. For example, HTML file uploads could be used to upload avatars or enable an internal team to upload product photos to a website or app.

In this tutorial, we will briefly examine file uploads in HTML and how to set them up from the frontend to the server, which receives the files.

What is an HTML file upload?

HTML provides a relatively simple solution for uploading files using the <input> element.

The <input> element is used to create interactive controls in a web form that permits users to enter data. Although it can be used for various types of data inputs, adding the type="file" attribute to the <input> element allows users to select files from their device for upload.

With the <input type="file"> element, you can create a file upload button for users to select files from their local device and upload them to your server or application.

Creating a file upload input in HTML would look something like this:

<input
  type="file"
  name="photos"
  accept="image/*"
  multiple
/>

Combining the type="file" attribute with additional attributes, you can perform more actions like the file upload button, limit the types of files that can be uploaded, and even gather metadata about the files being uploaded.

For example, if you want to only allow users to upload image files, you can use the accept attribute to specify the types of files that are allowed. The multiple attribute allows users to select multiple files at once.

<input
  type="file"
  name="photos"
  accept="image/*"
  multiple
/>

Now, when a user clicks on the button, they will only be able to select an image file from their device. And they can select multiple files at once too.

HTML file upload to server: Frontend to backend flow

The HTML file upload button you created is a first step in the process of uploading files to a server.

Once a user selects a file, the next step is to submit the file to the server for processing. This is typically done by submitting the form using a script, like JavaScript, to a backend service.

The backend service (which could be built with JavaScript, PHP, etc.) then processes the form submission data and saves it to the server and database, depending on the logic you have implemented.

Let’s see an example of how this works.

Frontend file upload flow

First, create a simple HTML form with a file input:

<form>
  <input
    type="file"
    name="photos"
    accept="image/*"
    multiple
  />
  <button type="submit">Upload</button>
</form>

Then, using JavaScript, handle the form submission and send the file data to a server endpoint:

document.querySelector('form').addEventListener('submit', e => {
  e.preventDefault(); 

  const formData = new FormData(); 

  const files = document.querySelector('input[type="file"]').files;

  for (let i = 0; i < files.length; i++) {
    formData.append('photos', files[i]);
  }
  
  fetch('/upload', {
    method: 'POST',
    body: formData,
  })
    .then(response => response.json())
    .then(data => {
      console.log('Success:', data);
    })
    .catch(error => {
      console.error('Error:', error);
    });
});

The code above listens for the form submission event, prevents the default behavior (browser redirect), and creates a FormData object to hold the files selected by the user. It then appends each file to the FormData object.

The FormData object is then sent to the server using the fetch API. The server endpoint /upload is where you would handle the file upload logic on the backend.

For a more detailed guide on how to handle file uploads with JavaScript, take a look at this tutorial on JavaScript file uploads.

If you use a front-end framework like React, Vue, or Angular, the process is similar, but you would use the framework’s specific methods for handling forms and file uploads. Here are some tutorials for popular frameworks:

👉 How to upload files in Astro

👉 How to upload a file in React/ React file upload

👉 How to upload a file in Angular

Backend file upload flow

On the server side, you need to implement the logic to handle the file upload. This can be done using a backend language like Node.js, PHP, Python, or another appropriate language. For example, in Node.js using Express, you could handle the file upload like this:

const express = require('express');
const multer = require('multer');

const upload = multer({ dest: 'uploads/' });

const app = express();

app.post('/upload', upload.array('photos'), (req, res) => {
  if (!req.files?.length) {
    return res.status(400).json({ error: 'No files uploaded' });
  }

  return res.status(200).json({ message: 'Files uploaded successfully!' });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

The server uses the multer middleware to handle file uploads.

The upload.array('photos') method acts as a middleware for each request to the /upload endpoint and catches the files uploaded by the user. The files are then saved in a destination directory called uploads/.

If the server successfully receives the files, it will respond with a success message. If there are any errors (such as no files being uploaded), it will respond with an error message.

More on this topic: 👉 How to upload files in Node.js

Challenges with large file uploads in HTML

The example above works well for small files, but what about when you need to handle large files? Large files are where you typically encounter challenges when uploading a file to the server.

Slow upload speed and latency

When you copy a huge file from a folder on your computer to a drive, it takes time, right? The same thing usually happens when you try to upload a large file to a server using HTML. Uploading a file is just like copying a file from your computer to another remote computer (the server). Since the server is not located in the same physical location as your computer, the process takes much longer.

Uploading a large file can be slow, and the latency (the time it takes for the server to respond to your request) can be high.

It gets worse if the user uploading the file has a slow internet connection or if your server’s location is far away (e.g., a user in South Africa uploading a 2 GB file to a server located in London).

Upload errors and timeouts

Since it takes more time to upload larger files, the chances of encountering upload errors or timeouts are high. This can happen if the server takes too long to respond or if the user’s internet connection becomes unstable. If the upload process is interrupted, the user may have to start over, which can be frustrating.

# Memory limits and server overload

Uploading a large file usually consumes a lot of memory on the server. At the same time, the server may be able to handle one user uploading a huge file. What happens if multiple users are uploading large files simultaneously? It can lead to server overloading and crashing.

This is especially true if the server has limited resources or if the file upload process is not optimized for handling large files

Mobile network constraints

Since many users access websites and applications via a mobile device, you also have to consider the user’s network.

Mobile networks typically have stricter data limits and slower speeds compared to wired connections, making it more difficult for a user to upload a large file on mobile devices.

They might experience issues like timeouts, network interruptions, or additional charges for exceeding their data limits.

Best techniques to upload large files in HTML

Thankfully, there are several techniques you can employ to overcome these challenges. Here are some of the best practices for uploading large files in HTML:

1. Chunked uploads

Chunked uploads involve breaking down large files into tiny pieces (chunks) and uploading them one at a time. By breaking the file into smaller chunks, the server is able to process each chunk individually, reducing the memory load and making it easier to handle large files.

Chunking a large file can also help with minimizing errors during upload, as when a chunk fails to upload, your code can retry that chunk instead of failing the entire file.

How does this work? When a user selects a large file to upload, the JavaScript code on the frontend splits the file into smaller chunks (e.g., 1 MB each) and sends each chunk to the server one by one. When all the chunks have been received, the backend code then reassembles the chunks into the original file and saves it to the server.

An example of implementing chunked uploads in HTML would look like this:

document.getElementById('upload-form').addEventListener('submit', e => {
  e.preventDefault();
  uploadFile();
});

async function uploadFile() {
  const fileInput = document.getElementById('file-upload');
  const file = fileInput.files[0];
  const chunkSize = 1 * 1024 * 1024; // 1MB per chunk

  if (!file) {
    alert('Please select a file!');
    return;
  }

  let start = 0;

  // Split the file into 10MB chunks
  while (start < file.size) {
    const chunk = file.slice(start, start + chunkSize);
    await uploadChunk(chunk);
    start += chunkSize;
  }
}

The code above listens for the form submission event, prevents the default behavior, and then starts uploading the file in chunks. The uploadChunk function would handle the actual upload of each chunk to the server.

Keep in mind that you need to implement the function to send each chunk to the server using the API or any other method you prefer. You would also need a backend endpoint to handle the chunk uploads and reassemble the file.

2. Resumable uploads

Another technique to handle large file uploads is resumable uploads. Since network conditions can be unpredictable, implementing resumable uploads will allow users to pause and resume the upload process without losing progress. When implemented, users can continue uploading from where they left off, which helps in cases of network interruptions or when other issues arise with a large file.

For a more detailed guide on this topic, refer to this tutorial on handling large file uploads.

HTML file upload example with Uploadcare

If you’d rather not deal with the complexities of handling large file uploads, you can use Uploadcare’s File Uploader. It provides a simple and efficient way to handle file uploads, including large files, without having to write complex code.

Plus, it comes with an easy-to-use interface that allows users to select files from their device, drag and drop files, and upload files from cloud storage services like Google Drive and Dropbox.

To use Uploadcare’s File Uploader, you need to include the Uploadcare library in your HTML file and then initialize the uploader:

<script type="module">
  import * as UC from 'https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@v1/web/file-uploader.min.js';
  UC.defineComponents(UC);
</script>
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@v1/web/uc-file-uploader-regular.min.css"
>

And in the <body> of your HTML, you’ll need to add the following code:

<uc-config
  ctx-name="my-uploader"
  pubkey="YOUR_PUBLIC_KEY"
>
</uc-config>

<uc-file-uploader-regular ctx-name="my-uploader"></uc-file-uploader-regular>

Where YOUR_PUBLIC_KEY is your Uploadcare Public Key from API Keys in your Uploadcare dashboard.

If you don’t have an Uploadcare account, you can sign up for free here

The <uc-config> element configures the uploader. Using the ctx-name attribute to identify the uploader and the pubkey attribute to specify your Uploadcare Public Key.

The <uc-file-uploader-regular> element creates the uploader. The ctx-name attribute specifies the uploader to which the configuration applies.

Tips to improve large file upload UX

When implementing file uploads in HTML, especially for large files, it’s essential to consider the user experience (UX).

Add drag-and-drop feature

A drag-and-drop feature allows users to easily upload files by dragging them from their file explorer and dropping them directly into the upload area. Having this feature can make the upload process more intuitive and user-friendly.

If you are using Uploadcare’s File Uploader, it already comes with built-in drag-and-drop. Users can simply drag files from their device and drop them into the upload area, but if you’d like to build your own drag-and-drop feature from scratch, you can check out this tutorial on how to implement drag-and-drop file uploads.

Show upload progress

Nothing is more frustrating than not knowing how long a request, like uploading a file, will take. Showing the upload progress gives users feedback on how long the upload will take and helps them understand the upload’s progress.

You can implement this by using the XMLHttpRequest object and then update a progress bar or percentage indicator on the UI, or build your own custom progress bar.

Preview before upload

Allowing users to preview files before uploading them can help them ensure they are uploading the correct file, especially for image uploads, where users can see a thumbnail of the image before submitting it.

This can be done by using the FileReader API to read the file and display a preview in the UI.

Provide clear error messages

When a user experiences upload errors, display an error message that explains both the error and the necessary steps to take to fix the error. Some of these issues may be related to file size restrictions, unsupported file types, or network connectivity problems.

It is also a great idea to provide users with the ability to retry their previous action after an error occurs so they can avoid having to start from scratch.

For a detailed guide on implementing these features, refer to this tutorial on improving file upload UX with JavaScript.

If you are using Uploadcare’s File Uploader, all of these features are built in, so you don’t have to worry about implementing them yourself. Instead, you can focus on integrating the uploader into your application and customizing it to fit your needs.

Conclusion: Choosing the right approach for HTML file uploads

In conclusion, uploading files in HTML is a straightforward process using the <input type="file"> element. However, as you move forward with your project, you may encounter challenges when dealing with large files or multiple file uploads. Implementing techniques like chunked and resumable uploads can be handy in overcoming these challenges and improving the user experience.

If you want to avoid the complexities of handling file uploads yourself, consider using Uploadcare’s File Uploader. It provides a simple and efficient way to handle file uploads, including large files, without writing complex code.

Start using Uploadcare’s File Uploader for free today and simplify your file upload process!

Build file handling in minutesStart for free

Ready to get started?

Join developers who use Uploadcare to build file handling quickly and reliably.

Sign up for free