Reputation: 11
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:
Desired Outcome: I’m looking for any solution (HTML, JavaScript, or otherwise) that could:
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.
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
Reputation: 82
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.
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