Add new Button to File Uploader in frappe

How could add a new button to the Frappe’s FileUploader. I am trying to add a scan button, but failing.

I have added a file under public/js/FileUploader.js, then added that in the hooks in app_include_js, but still nothing works.
Current code:

frappe.require("file_uploader.bundle.js", () => {

    const Base = frappe.ui.FileUploader;

    if (!Base) {

        console.error("Uploader not loaded");

        return;

    }

    // 🚨 IMPORTANT: patch the SAME reference used by Vue

    const originalUploadOptions =

        Base.UploadOptions =

        Base.UploadOptions || [];



    // prevent duplicates

    const exists = originalUploadOptions.some(

        o => o.label === "Scan Document"

    );

    if (!exists) {

        originalUploadOptions.push({

            label: "Scan Document",

            icon: `

                <circle cx="15" cy="15" r="15" fill="var(--subtle-fg)" />

                <path d="M8 10h8M8 14h8M8 18h5"

                      stroke="var(--text-color)"

                      stroke-linecap="round"/>

            `

            action: async ({ uploader, doctype, docname }) => {

                frappe.show_alert({

                    message: "Scanning...",

                    indicator: "blue"

                });



                const res = await frappe.call({

                    method: "app.api.scan_document",

                    args: { doctype, docname }

                });

                if (!res.message?.file_url) return;



                const file = await fetch(res.message.file_url)

                    .then(r => r.arrayBuffer())

                    .then(buf => new File([buf], "scan.png", {

                        type: "image/png"

                    }));

                uploader.add_files([file]);

                frappe.show_alert({

                    message: "Scan added",

                    indicator: "green"

                });

            }

        });


    }

});

Hi, if you want to add a button in form view, then use doctype_js = { } in hooks.py

// public/js/file.js

frappe.ui.form.on('File', {
    refresh: function(frm) {
        frm.add_custom_button(__('Scan Document'), function() {
            frappe.call({
                method: "your_app.your_module.doctype.your_doctype.your_method",
                args: {
                    docname: frm.doc.name
                },
                callback: function(r) {
                    if (r.message) {
                        frappe.msgprint(__('Updated Successfully'));
                        frm.reload_doc();
                    }
                }
            });
        });
    }
});

Hi @Vipul_Kumar ,
I want to add button to the File Uploader, not to a doctype:

did you try this after code change

bench build --app app_name
bench clear-cache
bench restart # restart the dev server (Ctrl+C and bench start)

yes, of course!

(function () {
	if (typeof window === "undefined" || typeof window.frappe === "undefined") return;

	frappe.provide("frappe.ui");

	function makePatched(Original) {
		if (!Original || Original.__scan_patched) return Original;

		class PatchedFileUploader extends Original {
			constructor(opts) {
				super(opts);
				if (this.dialog) {
					this.dialog.add_custom_action(__("Scan Document"), () => {
						frappe.call({
							method: "app_name.api.your_method",
							args: {},
							callback(r) {
								console.log(r);
							}
						});
					}, "btn-scan-document");
				}
			}
		}

		PatchedFileUploader.__scan_patched = true;
		return PatchedFileUploader;
	}

	let _CurrentFileUploader = frappe.ui.FileUploader ? makePatched(frappe.ui.FileUploader) : undefined;

	Object.defineProperty(frappe.ui, "FileUploader", {
		configurable: true,
		enumerable: true,
		get() { return _CurrentFileUploader; },
		set(value) { _CurrentFileUploader = value ? makePatched(value) : value; },
	});
})();

public/js/FileUploader.js

try this code

bench build --app app_name
bench clear-cache