Raed Abdelfattah
Raed Abdelfattah

Reputation: 11

How to Set Default Directory, Restrict Folder Access, and Enforce File Type Validation in <input type="file">?

I'm working on a file upload feature in an Angular project where users can upload specific files using an <input type="file"> element.

These are the html and css code snippets of the feature:

<label for="fileUpload" class="custom-file-upload">Load Parameters File</label>
<input type="file" id="fileUpload" style="display:none;" accept=".json,.xml">
.custom-file-upload {
  display: flex;
  cursor: pointer;
  background-color: #1c3849;
  color: white;
  border-radius: 6px;
  border: 1px solid black;
  box-sizing: border-box;
  align-items: center;
  justify-content: center;
  font: 15px "Noto Sans Display", sans-serif;
  font-weight: normal;
  width: 200px;
  height: 50px;
  margin: 0;
}

.custom-file-upload:hover {
  background-color: #006e9e;
}

I want the file explorer that opens when clicking "Choose file" to be validate the following criteria:

  1. Set a Default Directory: I want the file explorer to open in a specific default location when users are prompted to upload a file. I can't find a way to set a default folder for the file input dialog using standard HTML or TypeScript.
  2. Restrict File Explorer Access: I want to restrict users from navigating outside of certain folders (e.g., only allow them to browse specific directories). If this is not possible, at least I want to ensure that users cannot delete or rename any files while browsing.
  3. Enforce File Type Restrictions: Despite using the accept attribute in the element to limit file types (e.g., json or xml files), users can still manually select "all files" in the file dialog and upload files of other types as shown in the following screenshot: screenshot for file types restriction problem I want to fully prevent users from being able to select files outside the specified accept criteria.

Desired Outcome: I’m looking for any solution (HTML, JavaScript, or otherwise) that could:

  1. For Default Directory & Folder Restriction: I’ve looked into the File System Access API, but it doesn’t seem to fully allow setting a default directory or restricting user access in a way that matches my needs.

  2. For File Type Enforcement: While the accept attribute limits file types to an extent, users can still bypass this by manually selecting "all files" in the file picker dialog.

Upvotes: 1

Views: 56

Answers (1)

Paxon Kymissis
Paxon Kymissis

Reputation: 82

What is possible?

It looks like the file system access API will allow you to have greater control over what you want. The <input> tag is more limited, so I would recommend using a button or other tag with an onclick event instead.

First things first, you can disable other kinds of files by setting the excludeAcceptAllOption to true.

Second, we can start in a given directory using the startin feature. This could be a saved directory or some kind of default directory like 'Home' which is present on most operating systems.

For the last requirement, it is unfortunately impossible to restrict the user's ability to navigate to other directories or rename files since this is a default feature of most/all operating systems.

For the <input type='file'> approach, this only has the few attributes stated here. The problem is that none of these attributes are able to control renaming or browsing, or even the ability to see which files you have clicked but not decided to select. For the File System Access API, there is also nothing of the sort since all of the file picker options are provided here and do not relate to this.

An indirect method such as preventing the mouse from right-clicking a file to rename or seeing where the cursor is located to stop it from to another directory would also not work. This is because the mouse movement, clicking, and all other user inputs are not detectable while in the file picker. If you create an event listener for typing or clicking, it will be unresponsive since the file picker is not an element so event listeners cannot be added.

The point is that there is no way to control file renaming or the directory the user goes into since there is no way for the programmer to know if these have happened. They cannot be done directly since there are no built-in options.

What should I do?

I know this is disappointing, but my only suggestion would be to use the two possible features and to somehow get around the other one. For your element, you could change it to a button as mentioned before and use an event listener to activate the file picker.

The code would then look like this:

const format = {
  excludeAcceptAllOption: true,
  multiple: false,
  startin: window.navigator.platform.indexOf("Win") != -1 ? "D:/" : "Users/",
  types: [{
    description: "Your description here",
    accept: {
      "text/*": [".json", ".xml"],
    },
  }, ]
};
async function filePicker() {
  var fileHandle = await window.showOpenFilePicker(format);
  return fileHandle;
}

function clickFunction() {
  window.showOpenFilePicker(format)
  var file = filePicker();

  // Do something with your file
}
.custom-file-upload {
  display: flex;
  cursor: pointer;
  background-color: #1c3849;
  color: white;
  border-radius: 6px;
  border: 1px solid black;
  box-sizing: border-box;
  align-items: center;
  justify-content: center;
  font: 15px "Noto Sans Display", sans-serif;
  font-weight: normal;
  width: 200px;
  height: 50px;
  margin: 0;
}

.custom-file-upload:hover {
  background-color: #006e9e;
}
<label for="fileUpload" class="custom-file-upload">Load Parameters File</label>
<button id="fileUpload" style="display:none;" onclick="clickFunction()">

Important: this will not work in the browser snippet, so you will have to paste it into a text editor and run it locally.

Upvotes: 0

Related Questions