Explain Codes LogoExplain Codes Logo

How to set a value to a file input in HTML?

javascript
file-input
blob
data-transfer
Alex KataevbyAlex Kataev·Dec 17, 2024
TLDR

File inputs are locked boxes for security reasons—you cannot set a value to an <input type="file"> directly. However, you can trigger the file input dialog like so:

document.querySelector('#fileInput').click();

And grab the user-selected file using:

<input type="file" id="fileInput" hidden onchange="handleFiles(this)"> <button onclick="document.querySelector('#fileInput').click()">Upload File</button>

This approach preserves user control and autonomy over their files in an unobtrusive manner.

Security restraints—and how to work around them

Setting file input values programmatically with a client side disk system path is blocked by browsers. This is akin to a website reaching into your hard disk and grabbing files—clearly a privacy violation. However, these restrictions won't hinder our progress—we can still deal meaningfully with files while respecting boundaries!

Play nice with blobs and DataTransfer

If you have a Blob or File object from a server response or drag-and-drop operation, you can create a File object—like a mini file in the browser's sandbox—and add that to your file input. Here's how,

// Don't worry, we're octet-streaming, not daydreaming! const blob = new Blob(["file contents"], {type: 'application/octet-stream'}); const file = new File([blob], "yourFile.txt");

Now, take your freshly minted File object and simulate a drop event using the DataTransfer object:

// Say hello to our little friend, DataTransfer! const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); // And just like that, our input has files. No autographs, please. document.querySelector('#fileInput').files = dataTransfer.files;

Easy peasy lemon squeezy, right? You're basically harnessing the power of a very obedient postman who only delivers letters (files) you say are okay.

Plan B

No luck with the File and DataTransfer method? Here are a few other techniques to enhance user experience and bypass the restriction (legally, of course):

  • Image previews: Show users a sneak peek of their chosen image file.
  • File download links: Let users download files which they then can upload manually.
  • Clear/replace option: A checkbox or button to let users replace a previously selected file. Out with the old, in with the new!

Implementing the 'Impossible'—code snippets and caveats

Having crossed the security hurdle, time to get down to coding! Here's one way to fetch a file and manipulate your file input value using good 'ol JavaScript:

// Let's fetch; sorry, no dogs or frisbees here! fetch('https://example.com/file.txt') .then(response => response.blob()) .then(blob => { const file = new File([blob], "downloaded.txt"); const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); // Surprise, fileInput! You've got files! document.querySelector('#fileInput').files = dataTransfer.files; });

This script fetches a file and assigns this file to our file input by simulating user interaction.

UTF-8 character oopsies

It's not always sunshine and rainbows with File objects, especially with UTF-8 characters. To handle those curveballs, make a slight adjustment:

// Houston, we have UTF-8! const utf8Content = "你好,世界"; const blob = new Blob([new TextEncoder().encode(utf8Content)], {type: 'text/plain'}); const file = new File([blob], "utf8.txt"); // Aaand... we're back in the game.

Here, a handy TextEncoder steps in to ensure our precious UTF-8 characters don't run into encoding issues. Phew!