SendForm.net

HTML File Upload Input: Attributes, Limits and Browser Behaviour

A stylized browser window displaying an HTML file upload input field surrounded by floating document icons and interface elements.

The HTML file upload input is a single line of code, <input type="file">, that lets visitors pick files from their device and attach them to a form. You control what it accepts, whether people can select more than one file, and how the browser shows the picker, all through a handful of attributes. There is no built-in file size limit in the HTML itself, so any size cap you want has to come from JavaScript or your server.

The basic file upload input

At its core, a file upload input is just an input element with its type set to file:

<label for="resume">Upload your resume</label>
<input type="file" id="resume" name="resume">

The browser renders this as a button plus a small text label showing the chosen file (or "No file chosen" when empty). The exact wording and button style come from the browser and operating system, not from your CSS, which is why the control looks different in Chrome, Firefox, and Safari.

The name attribute matters: it is the key your server reads to find the uploaded data. Skip it and the file never reaches the server, even if everything else is perfect.

Attributes that shape the input

Beyond type and name, these are the attributes you will actually reach for:

Attribute What it does
accept Hints which file types the picker should show or prefer.
multiple Lets the user select more than one file at once.
capture On mobile, opens the camera or microphone directly instead of the file browser.
required Blocks form submission until at least one file is chosen.
disabled Greys out the control so it cannot be used or submitted.

A file input cannot use value to pre-fill a file for security reasons, and it ignores attributes like maxlength or pattern. If you are curious how disabled compares to read-only fields (spoiler: file inputs do not support read-only), the difference is explained in our guide on readonly versus disabled inputs.

The accept attribute in detail

The accept attribute filters what the file picker suggests. You can pass file extensions, MIME types, or wildcards, separated by commas:

<!-- Only PDFs and Word docs -->
<input type="file" accept=".pdf,.doc,.docx">

<!-- Any image type -->
<input type="file" accept="image/*">

<!-- A specific MIME type -->
<input type="file" accept="image/png">
The accept attribute is a hint, not a rule. It filters the file dialog to make selection easier, but a determined user can still switch the dialog to "All files" and pick something else. Always validate the file type again on the server.

Wildcards like audio/* , video/* , and image/* are handy when you want a whole category. Mixing extensions and MIME types in the same attribute works fine, and browsers treat them case-insensitively. The MDN reference on accept lists the full behaviour across browsers.

Allowing multiple file upload

Add the multiple boolean attribute and users can select several files in one go (Ctrl or Cmd click, or shift-select in the dialog):

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

A few things to know about multiple file upload:

  • The selected files land in the input's files property as a FileList, which you loop over in JavaScript.
  • For PHP and similar backends, using array-style names like photos[] lets the server receive them as an array.
  • Selecting new files replaces the previous selection; the input does not append. If you want an "add more" experience, you have to store files in JavaScript and manage the list yourself.

File size limits and where they live

Here is the part that trips people up: there is no maxsize attribute for a file upload input. HTML gives you zero control over the file size limit. Every real limit is enforced somewhere else:

Where How the limit is set
Client-side JavaScript Check input.files[0].size (in bytes) before submitting and warn the user early.
Web server (Nginx/Apache) Directives like client_max_body_size reject oversized requests.
Application runtime (PHP) upload_max_filesize and post_max_size in php.ini.

Client-side checks improve the experience but are not security. Anyone can bypass JavaScript, so your server must always enforce the real cap. A quick client-side guard looks like this:

const input = document.querySelector('#resume');
input.addEventListener('change', () => {
  const maxBytes = 5 * 1024 * 1024; // 5 MB
  if (input.files[0] && input.files[0].size > maxBytes) {
    alert('File is too large. Max 5 MB.');
    input.value = '';
  }
});
Validating uploads properly is part of a bigger picture. See our notes on securing form submissions for handling untrusted files, CSRF, and validation together.

Browser behaviour and quirks

File inputs behave slightly differently everywhere, and knowing the quirks saves debugging time:

  • Styling is limited. You cannot restyle the native button directly. The common trick is to hide the input with a visually-hidden class and trigger it by clicking a styled <label> tied to it via for.
  • The displayed path is fake. Browsers show C:\fakepath\filename.jpg instead of the real path. This is a deliberate privacy feature and has been standard since the mid-2000s.
  • Mobile turns capture into a shortcut. On phones, accept="image/*" capture="environment" can open the rear camera straight away, while capture="user" targets the front camera.
  • Clearing a selection needs code. There is no native "clear" button; set input.value = '' in JavaScript to reset it.

Wiring it into a working form

A file input only sends its contents when the surrounding <form> uses the correct encoding. For file uploads you must set enctype="multipart/form-data", otherwise the browser sends only the file name, not the file:

<form action="/upload" method="post" enctype="multipart/form-data">
  <input type="file" name="document" required>
  <button type="submit">Send</button>
</form>

That enctype choice is the single most common reason uploads silently fail, so it is worth reading why in our deep dive on HTML form enctype. The action attribute points to the endpoint that receives the file, and getting it right is covered in our explainer on what the form action attribute actually does. If your form also collects longer text like cover letters or comments, a textarea element pairs naturally with the file field.

HTML file upload input inside a working contact form

Collect file uploads without building a backend

Want an HTML file upload input that actually delivers submissions somewhere? Our contact form endpoint handles the multipart data and file attachments for you, so you can focus on the markup instead of server config.

Try our free form endpoint →

Frequently asked questions

No. There is no size attribute for file inputs in HTML. You enforce a file size limit with JavaScript by reading the file's size property before submission, and always again on your server or in your runtime config. Client-side checks only improve the user experience.

Not reliably. The accept attribute filters the file picker dialog to make choosing easier, but users can switch to "All files" and select anything. Treat it as a convenience hint, then validate the actual file type on the server before accepting it.

Add the multiple attribute to the input. Users can then shift or Ctrl click several files in the dialog. The selection arrives as a FileList you loop through in JavaScript, and using array-style names like files[] helps servers such as PHP receive them as an array.

The most common cause is a missing enctype. A form containing a file input must set enctype to multipart/form-data. Without it, the browser sends only the file name as text, not the file contents. Also confirm your input has a name attribute.

That fake path is a deliberate privacy protection built into browsers. Exposing the true local path could leak information about a user's system and folder structure. Your code should rely on the file's name and contents through the files property, never the displayed path string.