fix(file-upload): add support for blocking unsupported file types in file uploader (#36736)

* feat: add support for blocking unsupported file types in file uploader

* chore: pre-commit fix formatting

* fix: restrict image type in file upload and show better errors

* chore: allow all image types by default

Simplified allowed file types for image uploads to 'image/*'.

* chore: allow all image types by default

---------

Co-authored-by: Ankush Menat <ankush@frappe.io>
This commit is contained in:
Prathamesh Kurunkar 2026-02-06 15:07:19 +05:30 committed by GitHub
parent eb59ab2817
commit fe5072fa23
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 46 additions and 6 deletions

View file

@ -284,6 +284,7 @@ const props = defineProps({
max_file_size: null, // 2048 -> 2KB
max_number_of_files: null,
allowed_file_types: [], // ['image/*', 'video/*', '.jpg', '.gif', '.pdf'],
blocked_file_types: [], // ['image/heic', 'image/tiff'],
crop_image_aspect_ratio: null, // 1, 16 / 9, 4 / 3, NaN (free)
}),
},
@ -472,6 +473,7 @@ function check_restrictions(file) {
let is_correct_type = true;
let valid_file_size = true;
let is_unsupported_file_type = check_unsupported_file_type(file);
if (allowed_file_types && allowed_file_types.length) {
is_correct_type = allowed_file_types.some((type) => {
@ -493,12 +495,22 @@ function check_restrictions(file) {
valid_file_size = file.size < max_file_size;
}
if (!is_correct_type) {
if (!is_correct_type || is_unsupported_file_type) {
console.warn("File skipped because of invalid file type", file);
frappe.show_alert({
message: __('File "{0}" was skipped because of invalid file type', [file.name]),
indicator: "orange",
});
if (is_unsupported_file_type) {
frappe.show_alert({
message: __('File "{0}" was skipped because of unsupported file type "{1}"', [
file.name,
file.type,
]),
indicator: "orange",
});
} else {
frappe.show_alert({
message: __('File "{0}" was skipped because of invalid file type', [file.name]),
indicator: "orange",
});
}
}
if (!valid_file_size) {
console.warn("File skipped because of invalid file size", file.size, file);
@ -511,8 +523,22 @@ function check_restrictions(file) {
});
}
return is_correct_type && valid_file_size;
return is_correct_type && valid_file_size && !is_unsupported_file_type;
}
function check_unsupported_file_type(file) {
let { blocked_file_types = [] } = props.restrictions;
return blocked_file_types.some((type) => {
if (type.includes("/")) {
if (!file.type) return false;
return file.type.match(type);
}
if (type[0] === ".") {
return file.name.toLowerCase().endsWith(type.toLowerCase());
}
});
}
function upload_files(dialog) {
if (show_file_browser.value) {
return upload_via_file_browser();

View file

@ -65,6 +65,13 @@ frappe.ui.form.ControlAttach = class ControlAttach extends frappe.ui.form.Contro
on_attach_doc_image() {
this.set_upload_options();
this.upload_options.restrictions.allowed_file_types = ["image/*"];
// file types like .heic/.tiff are not supported for preview directly in the browser, so we block the user from uploading them
this.upload_options.restrictions.blocked_file_types = [
"image/heic",
"image/heif",
"image/tiff",
"image/tif",
];
this.file_uploader = new frappe.ui.FileUploader(this.upload_options);
}
set_upload_options() {

View file

@ -21,5 +21,12 @@ frappe.ui.form.ControlAttachImage = class ControlAttachImage extends frappe.ui.f
set_upload_options() {
super.set_upload_options();
this.upload_options.restrictions.allowed_file_types = ["image/*"];
// file types like .heic/.tiff are not supported for preview directly in the browser, so we block the user from uploading them
this.upload_options.restrictions.blocked_file_types = [
"image/heic",
"image/heif",
"image/tiff",
"image/tif",
];
}
};