· 4 min read

The form Tag and FormData in Practice

This article was auto-translated from Chinese. Some nuances may be lost in translation.

In the previous article, we introduced the multipart/form-data request format and the problem it aims to solve. In this article, we will explain practical problems and use cases encountered in real-world development.

Specifically, this article covers the following topics related to form applications:

  • What happens under the hood with the <form/> tag
  • Using FormData in JavaScript
  • Combining FormData with fetch
  • How JavaScript handles file uploads

Revisiting the form Tag

HTML’s form tag actually has many implementation details handled by the browser that developers sometimes overlook. Take the following example:

<form method="POST" action="/upload" enctype="multipart/form-data">
  <input type="text" name="name" />
  <input type="file"  name="file" />
  <button>
    Submit
  </button>
</form>

Without any JavaScript code, clicking the Submit button prompts the browser to handle these tasks for you:

  • Serialize the name and file input fields
  • Send an HTTP request using the POST method with Content-Type: multipart/form-data
  • Read the file and append it to the request payload (if the file exists)

Before single-page applications and front-end frameworks became popular, filling out a form, submitting it, and redirecting to another page was the standard approach. However, as the amount of input data grew or when only part of the page needed an update (such as posting a comment), having a full page reload every time provided a poor user experience. Consequently, the practice of calling APIs via AJAX and dynamically updating the UI with JavaScript gradually emerged.

Desktop - 1

Although dynamic updates indeed improved user experience, implementing good form design requires considering many details:

  • Error handling
  • State transitions
  • Data persistence
  • Accessibility

Often, if just one of these aspects is handled poorly, users might even prefer the simplicity of a classic full-page refresh form. For admin dashboards or back-office applications, using <form> elements with full-page refreshes can often save significant development time and may even run more reliably by leveraging the browser’s built-in mechanisms.

Using FormData in JavaScript

FormData defines an interface that makes it easy for developers to work with key/value pairs, most commonly in form handling. You can instantiate and use FormData like this:

const formData = new FormData()
//                key     value
formData.append('name', 'Kalan');

If you pass a form element into FormData, it will automatically serialize the input values directly into the FormData object:

<form id="form" enctype="multipart/form-data" action="/upload" method="POST">
  <input type="text" name="name" />
  <input type="file" name="file" />
  <button>Submit</button>
</form>

<script>
  const formData = new FormData(document.getElementById('form'));
  formData.get('name'); // 取得目前 input 的值
  formData.get('file'); // 取得目前的檔案
</script>

FormData 在 JavaScript 的應用

In addition, if you pass FormData into the body of fetch, the browser will automatically send it formatted as multipart/form-data:

const formData = new FormData();
formData.append('name', 'Kalan');
formData.append('file', new File(['Hello World'], 'file.txt', { type: 'text/plain' }))

fetch('/upload', {
  method: 'POST',
  body: formData
})

After executing the JavaScript code above and inspecting the Network tab, you will notice that even though Content-Type was not explicitly defined, the browser still sends it as multipart/form-data, and the serialization of the form data is also handled by the browser.

用 fetch 與 FormData 傳送 multipart form-data 請求

Summary

These two articles have covered the use cases and practical applications of multipart/form-data. The first article explained the meaning of Content-Disposition, the purpose of boundaries, and how a multipart/form-data request is constructed. This second article demonstrated how to practically use forms and FormData, as well as how to manipulate FormData and handle file uploads using JavaScript.

For the server, a file upload from a web page is essentially just an HTTP request. The server must parse the data based on the header information and the format defined by multipart/form-data to extract the file content correctly. Typically, this parsing is already handled by backend frameworks, but it is worth emphasizing that there is no magic behind uploading files on the web—it is fundamentally built upon HTTP requests.

Related Posts

Explore Other Topics