How to Upload Files in 2022?

Can we finally do away with the Input Element and FileReader API?

Disclaimer: This post involves the context of handling and reading files within a JavaScript-based web application. There’s nothing wrong with using an input element for file …


This content originally appeared on DEV Community and was authored by Ezell Frazier

Can we finally do away with the Input Element and FileReader API?

Disclaimer: This post involves the context of handling and reading files within a JavaScript-based web application. There's nothing wrong with using an input element for file uploads for other purposes. However, it's wonderful to have an alternative approach.

The Old Way of Uploading Files with JavaScript

So, I'm writing an application and I want to allow for users to save and load their configurations. JSON is likely the simplest approach here. Or, I'd think.

<input type="file" accept=".json" id="upload"/>
const uploadElement = document.getElementById('upload')

const reader = new FileReader();

// Two event handlers to for uploading and reading files
reader.onload = () => {
  const json = reader.result
  const data = JSON.parse(json)
  console.log(data)
}

uploadElement.onchange = (e) => {
  const [file] = e.target.files
  reader.readAsText(file)
}

The old approach involves declaring two input handlers for two asynchronous operations. The reader object can read uploaded files, however reader.result is not available in a traditional sequence, as seen below:

const uploadElement = document.getElementById('upload')

const reader = new FileReader();

uploadElement.onchange = (e) => {
  const [file] = e.target.files
  reader.readAsText(file)
  console.log(reader.result) // why is this null?
}

reader.result is null because it hasn't finished reading the file. So, a workaround involves using the reader's readAsText method in tandem with a Promise constructor.

const uploadElement = document.getElementById("upload");

const reader = new FileReader();

// Poll for changes to the filereader's state about every 25ms
const readTextAsync = (filereader, fileBlob) =>
  new Promise((resolve) => {
    let interval;
    filereader.readAsText(file);

    interval = setInterval(() => {
      if (filereader.readyState === FileReader.DONE) {
        clearInterval(interval);
        const result = filereader.result;
        resolve(result);
      }
    }, 25);

  });

uploadElement.onchange = async (e) => {
  const [file] = e.target.files;
  const json = await readTextAsync(reader, file)
  console.log(json) // We have our json string
};

There's no longer two event handlers, but there's more code.

Converting callback-based APIs into something more modern may be more tedious to write, harder to read, and possibly introduce more opportunities for bugs.

Uploading files with the File System Access API

<button id="upload">Select a File</button>
const uploadBtn = document.getElementById("upload");

// I can clearly see and understand what's happening here
uploadBtn.onclick = async () => {
  const options = {
    types: [
      {
        description: "JSON",
        accept: {
          "application/json": [".json"],
        },
      },
    ],
  };
  const [fileHandle] = await window.showOpenFilePicker(options);
  const file = await fileHandle.getFile();
  const json = await file.text();
  console.log(json);
};

There's many improvements to the developer experience here. window.showOpenFilePicker allows us to place the following all in one callback function:

  • File reading
  • File parsing
  • File Picker Options

However, the biggest benefit is not having tightly related implementation details within multiple places across multiple files, across multiple steps.

Lastly, the input element may introduce a design which clashes with the overall theme of the UI. It's not uncommon to see implementations of a button element for file uploading, while hiding the actual input element responsible for the file upload.

None of that is required here.

Caveats

  • The File System Access API is fully supported within Chrome and Edge browsers as of this post. However, Polyfills are available
  • The FileSystem API only works in secure, https:// environments, with the exception of localhost
  • The FileSystem API also won't work within iframes or other framed environments like CodePen / CodeSandbox, etc.

Learn more about the File System Access API on MDN


This content originally appeared on DEV Community and was authored by Ezell Frazier


Print Share Comment Cite Upload Translate Updates
APA

Ezell Frazier | Sciencx (2022-06-03T18:34:28+00:00) How to Upload Files in 2022?. Retrieved from https://www.scien.cx/2022/06/03/how-to-upload-files-in-2022/

MLA
" » How to Upload Files in 2022?." Ezell Frazier | Sciencx - Friday June 3, 2022, https://www.scien.cx/2022/06/03/how-to-upload-files-in-2022/
HARVARD
Ezell Frazier | Sciencx Friday June 3, 2022 » How to Upload Files in 2022?., viewed ,<https://www.scien.cx/2022/06/03/how-to-upload-files-in-2022/>
VANCOUVER
Ezell Frazier | Sciencx - » How to Upload Files in 2022?. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/06/03/how-to-upload-files-in-2022/
CHICAGO
" » How to Upload Files in 2022?." Ezell Frazier | Sciencx - Accessed . https://www.scien.cx/2022/06/03/how-to-upload-files-in-2022/
IEEE
" » How to Upload Files in 2022?." Ezell Frazier | Sciencx [Online]. Available: https://www.scien.cx/2022/06/03/how-to-upload-files-in-2022/. [Accessed: ]
rf:citation
» How to Upload Files in 2022? | Ezell Frazier | Sciencx | https://www.scien.cx/2022/06/03/how-to-upload-files-in-2022/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.