【问题标题】:Programmatically trigger "select file" dialog box以编程方式触发“选择文件”对话框
【发布时间】:2021-03-07 08:34:34
【问题描述】:

我有一个隐藏的文件输入元素。是否可以从按钮的点击事件中触发其选择文件对话框?

【问题讨论】:

    标签: javascript jquery html


    【解决方案1】:

    如果您希望拥有自己的按钮来上传文件而不是使用<input type="file" />,您可以执行以下操作:

    <input id="myInput" type="file" style="visibility:hidden" />
    <input type="button" value="Show Dialog" onclick="$('#myInput').click();" />
    

    请注意,我使用了visibility: hidden,而不是display: none。您不能在未显示的文件输入上调用 click 事件。

    【讨论】:

    • 基本情况直截了当,但与许多浏览器不兼容。请注意,将此解决方案与在 opacity:0 的按钮上覆盖文件输入元素相结合是一个更好的主意,正如 Xeon06 的回答中所提到的那样。
    • 更新:在现代浏览器中,您可以单击甚至不在 DOM 中的输入。太棒了!
    • 我刚刚在display:none 输入上尝试了click(),它成功了
    • 是的,在 2015 年,click()ing 与 display: none 一起工作的元素! ;) 在过去的四年里事情发生了怎样的变化。
    • 您可以使用hidden 属性代替style="visibility:hidden": &lt;input id="myInput" type="file" hidden&gt; (w3schools.com/tags/att_global_hidden.asp)
    【解决方案2】:

    这里的大多数答案都缺少有用的信息:

    是的,您可以使用 jQuery/JavaScript 以编程方式单击输入元素,但前提是您在属于由用户启动的事件的事件处理程序中执行此操作!

    因此,例如,如果您(脚本)以编程方式单击 ajax 回调中的按钮,则不会发生任何事情,但如果您将同一行代码放入用户引发的事件处理程序中,它将起作用。

    附: debugger; 关键字如果在程序点击之前会中断浏览窗口......至少在 chrome 33 中......

    【讨论】:

    • 正如@LouisBataillard 正确提到的:不仅原始事件处理程序需要由用户发起;它必须是一个特定的点击事件。这是他提供的一个小提琴来证明这一点:link
    • 您可以点击动态生成的内容。在 jquery 中,即$(staticElementParent).on("click", "dynamicChild", function(){})
    • 谢谢!!!!我一直在 javascript 控制台中测试所有这些答案,我已经疯了!
    • 我已经挣扎了半个小时,以编程方式提示文件输入窗口。 NOBODY ELSE 表示,如果活动不是由用户发起,那是不可能的……你应该得到很多 +1。
    • 从 Chrome 62 开始,debugger; 关键字不再干扰程序化点击
    【解决方案3】:

    仅作记录,有一个不需要 javascript 的替代解决方案。这有点像 hack,利用了点击标签将焦点设置在相关输入上的事实。

    你需要一个&lt;label&gt; 和一个正确的for 属性(指向输入),可选地样式像一个按钮(使用引导程序,使用btn btn-default)。当用户点击标签时,对话框打开,例如:

    <!-- optionnal, to add a bit of style -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"/>
    
    <!-- minimal setup -->
    <label for="exampleInput" class="btn btn-default">
      Click me
    </label>
    <input type="file" id="exampleInput" style="display: none" />

    【讨论】:

    • 我喜欢这个,不想在我的 Angular 项目中包含完整的 jQuery,效果很好:)
    • 这种行为在所有现代浏览器中都可靠吗?
    • 这在没有任何 JS 的情况下工作,使用本机浏览器行为。与 onDrop 事件配合使用,实现功能丰富的文件上传效果非常好!
    • 我不得不摆弄 CSS,但后来它起作用了 - 即具有“显示:无”的文件输入可见性在所有浏览器中都不好。 (但不透明度为0等都可以)
    【解决方案4】:

    我不确定浏览器如何处理对 type="file" 元素的点击(安全问题和所有问题),但这应该可以:

    $('input[type="file"]').click();
    

    我在 Chrome、Firefox 和 Opera 中测试了 this JSFiddle,它们都显示了文件浏览对话框。

    【讨论】:

    • 这似乎只在“调用”事件本身就是点击事件时才有效。例如,似乎无法根据hover 事件打开文件对话框:jsfiddle.net/UQfaZ/1
    • 如果输入不在 DOM 中,您知道如何使用 Selenium 进行测试吗?
    【解决方案5】:

    我将input[type=file] 包装在标签标签中,然后根据自己的喜好设置label 的样式,并隐藏input

    <label class="btn btn-default fileLabel" data-toggle="tooltip" data-placement="top" title="Upload">
        <input type="file">
        <span><i class="fa fa-upload"></i></span>
    </label>
    
    <style>
        .fileLabel input[type="file"] {
            position: fixed;
            top: -1000px;
        }
    </style>
    

    纯 CSS 解决方案。

    【讨论】:

    • 只需设置 &lt;input type="file" hidden&gt; 即可消除应用 CSS 样式的需要。
    【解决方案6】:

    如今,像这样的混合解决方案可以获得最佳体验,

    let fileHandle;
    async function fileOpen() {
        [fileHandle] = await window.showOpenFilePicker();
        const file = await fileHandle.getFile();
        console.log(await file.text());
    }
    // The advantage of this is fileHandle can be used to save to
    // the opened file itself later, read more on this in https://web.dev/file-system-access/
    
    
    // in April 2021, window.showOpenFilePicker still not support in Safari
    // so one should have this around also
    function legacyFileOpen() {
        var input = document.createElement('input');
        input.type = 'file';
        input.onchange = function () {
            input.files[0].arrayBuffer().then(function (arrayBuffer) {
                console.log(new TextDecoder().decode(arrayBuffer));
            });
        }
        input.click();
    }
    

    【讨论】:

      【解决方案7】:

      不幸的是,本来唯一的方法是创建一个&lt;input type="file"&gt; 元素,然后模拟点击。

      有一个小插件(无耻插件)可以消除一直这样做的痛苦:file-dialog

      fileDialog()
          .then(file => {
              const data = new FormData()
              data.append('file', file[0])
              data.append('imageName', 'flower')
      
              // Post to server
              fetch('/uploadImage', {
                  method: 'POST',
                  body: data
              })
          })
      

      【讨论】:

        【解决方案8】:

        最好的解决方案,适用于所有浏览器......甚至在移动设备上。

        <div class="btn" id="s_photo">Upload</div>
        
        <input type="file" name="s_file" id="s_file" style="opacity: 0;">';
        
        <!--jquery-->
        
        <script>
            $("#s_photo").click(function() {
                $("#s_file").trigger("click");
            });
        </script>
        

        隐藏输入文件类型会导致浏览器出现问题,不透明度是最好的解决方案,因为它不会隐藏,只是不显示。 :)

        【讨论】:

        • 你应该提到这需要一个 jquery 引用。
        • 不透明度涉及一个完全不相关的概念——如果它不影响带有“透视”元素的布局,那你就很幸运了。该元素应该存在,但不可见,因此visibility:hidden 应该是更好的选择。
        • visibility: hidden 仍然会影响布局。 display: none 是你想要的。
        【解决方案9】:

        出于安全原因,没有跨浏览器的方法。人们通常做的是将输入文件覆盖在其他东西上并将其可见性设置为隐藏,以便它自己触发。 More info here.

        【讨论】:

        • OP 说的是&lt;input type="file"&gt;,而不是&lt;select&gt;
        • 没问题。我以前自己做过。针对您的编辑,一种方法可以做到;通过使用 jQuery $.click() 触发元素的点击事件。
        • @JamWaffles 好吧,这很奇怪。我清楚地记得几周前花了一整天的时间。它在 Firefox 和 IE 中不起作用。我想知道这笔交易是什么......
        • 很好奇。我的答案中有一个适用于 FF 的 JSFiddle。我无法在 IE 中测试(我在 Linux 上),所以我不知道这是否还会出现。
        • 很好的研究工作!如果每次网络开发人员不得不将一些非常正常的行为改造成某些东西时,我都会花一分钱,我会变得非常富有。
        【解决方案10】:

        确保您在 REACT 中使用绑定来获取组件道具

        class FileUploader extends Component {
          constructor (props) {
            super(props);
            this.handleClick = this.handleClick.bind(this);
          }
           onChange=(e,props)=>{
            const files = e.target.files;
            const selectedFile = files[0];
            ProcessFileUpload(selectedFile,props.ProgressCallBack,props.ErrorCallBack,props.CompleatedCallBack,props.BaseURL,props.Location,props.FilesAllowed);
          }
           handleClick = () => {
            this.refs.fileUploader.click();
          }
          render()
          {
          return(
              <div>
                <button type="button" onClick={this.handleClick}>Select File</button>  
                <input type='file' onChange={(e)=>this.onChange(e,this.props)} ref="fileUploader" style={{display:"none"}} />
              </div>)
          }
        }
        

        【讨论】:

          【解决方案11】:

          以编程方式浏览文件

          
          
          function browseFile(accept) {
              const promise = resolvingPromise();
              const input = document.createElement('input');
              input.type = "file";
              input.accept = accept;
              input.onchange = function (e) {
                  const files = e.target.files;
                  promise.resolve(files);
              }
              setTimeout(function () {
                  click(input);
              }, 0);
              return promise;
          }
          
          function click(node) {
              try {
                  node.dispatchEvent(new MouseEvent('click'))
              } catch (e) {
                  const evt = document.createEvent('MouseEvents')
                  evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null)
                  node.dispatchEvent(evt);
              }
          }
          
          
          

          【讨论】:

            【解决方案12】:

            使用jQuery你可以调用click()来模拟点击。

            【讨论】:

              【解决方案13】:

              这对我有用:

              $('#fileInput').val('');
              

              【讨论】:

                【解决方案14】:

                对于那些想要相同但使用 React 的人

                openFileInput = () => {
                    this.fileInput.click()
                }
                

                <a href="#" onClick={this.openFileInput}>
                    <p>Carregue sua foto de perfil</p>
                    <img src={img} />
                </a>
                <input style={{display:'none'}} ref={(input) => { this.fileInput = input; }} type="file"/>
                

                【讨论】:

                  【解决方案15】:
                  <div id="uploadButton">UPLOAD</div>
                  <form action="[FILE_HANDLER_URL]" style="display:none">
                       <input id="myInput" type="file" />
                  </form>
                  <script>
                    const uploadButton = document.getElementById('uploadButton');
                    const myInput = document.getElementById('myInput');
                  
                    uploadButton.addEventListener('click', () => {
                      myInput.click();
                    });
                  </script>
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多