Javascript 已拦截 "Ctrl+O" 未打开我的文件对话框

Javascript Intercepted "Ctrl+O" Does Not Open My File Dialog

我的 HTML 中有一个 <input type="file" id="browse-button"/> 文件浏览器输入。

我有另一个 ID 为 choose-file-button 的按钮,单击该按钮会调用 document.getElementById("browse-button").click();。单击此按钮时,它会正确单击 #browse-button 并打开文件对话框。

现在,我从 this answer 中获取代码来拦截 Ctrl+O 按键并打开我的文件对话框,所以我有这个:

$(window).bind('keydown', function(e)
{
    if (e.ctrlKey || e.metaKey)
    {
        switch (String.fromCharCode(e.which).toLowerCase())
        {
            case 's':
                e.preventDefault();
                // doesn't matter for this question
                return false;
            case 'o':
                e.preventDefault();
                document.getElementById("choose-file-button").click();
                return false;
        }
    }
    return true;
});

如您所见,当我拦截 Ctrl+O 时,我单击了我的 #choose-file-button 按钮,该按钮在其 onclick 处理程序中调用 document.getElementById("browse-button");。我在这个点击处理程序中放置了一个断点,当我按下 Ctrl+O 时,它确实到达了这个断点。但是,文件对话框从未出现。

通过调试,我发现如果我在 #choose-file-button click() 行后面放一个 alert(...);,那么警报会显示 正常页面 "Open File" 对话框出现(不是我的文件对话框)。但是,如果我没有此警报,则什么也不会显示。

这是一个错误吗?我该如何修复它并通过截获的 Ctrl+O?

显示我的文件对话框

编辑:我刚刚在 Chrome 中进行了测试,它运行良好。但是,它在 Firefox 中仍然不起作用。

这里有一些浏览器安全魔法。当使用超时或间隔或我尝试的任何其他方法时,代码正常运行但浏览器只是拒绝打开文件上传对话框。这可能是故意的,以阻止恶意 JS 在未经同意的情况下尝试获取用户的文件。但是,如果您绑定到 link 上的点击事件,它可以完美地使用 jQuery 或常规 JS。

编辑:据怀疑,大多数浏览器都会根据事件的类型以及它是由用户创建还是以编程方式生成来跟踪事件是否可信。请参阅 以获取完整详细信息。如您所见,由于键盘事件不在列表中,因此永远无法信任它们。

Test JSFiddle

<form action="#" method="post">
    <div>
        <input type="file" id="myfile" name="myfile" /> <a href="#" id="mylink" accesskey="o">Click me</a>
    </div>
</form>

$("#mylink").click(function () {
    $("#myfile").click();
});

$(window).bind('keydown', function (e) {
    if (e.ctrlKey || e.metaKey) {
        switch (String.fromCharCode(e.which).toLowerCase()) {
            case 'o':
                e.preventDefault();
                console.log("1a");

                $("#myfile").click();
                //alert("hello");

                console.log("1b");
                return false;
        }
    }
    return true;
});

我认为这里只有两个选项,它们都是变通方法,而不是解决方案。

  • 一种是使用 link 触发文件上传对话框,并要求人们使用 ALT+SHIFT+O 而不是 CTRL+O(因为我在 link 在示例中)。
  • 另一种选择是为 drag-drop file uploading.
  • 使用新的 HTML5 JavaScript API 之一

附录:我还尝试在 Firefox 中使用纯 JavaScript 来获取点击事件并使用 isTrusted 属性 检查它是否可信。对于 link 上的点击,它返回 true。但是,尝试在别处存储和重用该事件是行不通的,因为在您获得对它的引用时它已经被分派了。此外,不出所料,创建新事件并尝试设置 isTrusted = true 也不起作用,因为它是只读的。

浏览器将许多 Ctrl+ 快捷键映射到自己的命令,例如 CTRL+O 打开文件(在 firefox 中)。

同时,当您尝试覆盖 javascript 中的此类快捷方式时,浏览器的行为会有所不同。有些浏览器允许您这样做,有些则不允许,有时默认的浏览器操作可能会与您的 javascript.

的操作一起弹出。

这是讨论此问题的另一个话题 topic

您最好选择不同的快捷方式。

您可以尝试使用 Mousetrap 库。它覆盖了键捕获造成的大多数问题。 官网及完整参考:

https://craig.is/killing/mice

祝你好运

您不能在所有浏览器中都这样做,据我所知,只有 IE 允许这样做。我猜这是由于安全问题,所以程序员不能自动在 HTML 文件元素上设置文件名(未经客户许可)。

查看此 link 了解更多详情:

In JavaScript can I make a "click" event fire programmatically for a file input element?

Show input file dialog on load?