Joseph
Joseph

Reputation: 4725

<input type="file"> accept property will be ignored when drag and drop file, how can I prevent this?

I want to force the user to only select a CSV or excel file.

Please see this minimum example:

<input type="file" accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel">

Although I can use accept property to force the file selector not to select other files, I can still use drag and drop files directly from Finder, and it will works--the accept property will be ignored.

Is it possible to prevent this?

Upvotes: 3

Views: 1708

Answers (3)

Maimas2
Maimas2

Reputation: 961

You just have to add an event listener and function to either accept or reject the file:

fileInput.addEventListener("change", func);

var func = function() {
  if(fileInput.files[0].type == /*insert your file types here*/) {
    //accept file and do stuff with it
  } else {
    //reject and tell user that is was rejected and why
  }
}

I am not sure this works with the drag & drop file input, but I know it works with the regular type. The change event is called whenever the file changes.

Upvotes: 0

Unmitigated
Unmitigated

Reputation: 89442

You will need to perform server-side validation, but you can make the user experience better by checking the type of the file against a Set of allowed types.

const allowedTypes = new Set(['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 
   'application/vnd.ms-excel']);
document.querySelector('input[type=file]').addEventListener('change', function(){
  if(!allowedTypes.has(this.files[0].type)){
    console.log("Not a CSV file");
    this.value = '';//clear the input for invalid file
  } else {
    console.log("CSV file");
  }
});
<input type="file" accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel">

Upvotes: 3

Saadi Toumi Fouad
Saadi Toumi Fouad

Reputation: 2829

Note that csv files has many MimeTypes so you should check for more than "application/vnd.ms-excel" => .CSV Mimetypes, and you can check against that in client side as well by comparing the type of the file against an array of your accepted types that way you can add or delete the way that fits your needs

// the list of the accepted types since we need it always it's better to
// make it global instead of local to the onchange litener, and even you can
// add other types dynamically as well;
const acceptedTypes = ["text/csv", "text/x-csv", "application/x-csv", "application/csv", "text/x-comma-separated-values", "text/comma-separated-values", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.ms-excel"];
document.querySelector("[type='file']").onchange = function() {
  if(!acceptedTypes.includes(this.files[0].type)) {
    console.log("This file is not allowed for upload");
    // if the file is not allowed then clear the value of the upload element
    this.value = "";
  }
};

And if you want this behaviour only when the user drags and drops the file then you can customize it like this

const acceptedTypes = ["text/csv", "text/x-csv", "application/x-csv", "application/csv", "text/x-comma-separated-values", "text/comma-separated-values", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.ms-excel"];
// global variable to hold if the user has dragged the file or not
let isDragged = false;
// the `ondragover` gets triggered before the `onchange` event so it works as expected
document.querySelector("[type='file']").ondragover = function() {
  isDragged = true;
};
document.querySelector("[type='file']").onchange = function() {
  // if there was no drag then do nothing
  if(!isDragged) return;
  if(!acceptedTypes.includes(this.files[0].type)) {
    console.log("This file is not allowed for upload");
    // if the file is not allowed then clear the value of the upload element
    this.value = "";
  }
  isDragged = false;
};

Upvotes: 1

Related Questions