【问题标题】:How to open select file dialog via js?如何通过js打开选择文件对话框?
【发布时间】:2013-04-19 09:47:20
【问题描述】:
$('#id').click();

它不适用于 Mac OS 上的 Chrome 26。

问题实际上是创建可以集成到表单中的“上传”小部件。 小部件将由两部分组成。第一部分是带有启动器按钮和错误/成功消息的 div。 我认为方法是将另一个表单作为文件输入的第二部分并将文件提交到 iframe。提交后,我们在主表单的第一部分填写隐藏字段或显示错误。

简单的方法是将文件表单添加到主表单中,但被禁止。

【问题讨论】:

  • 幸运的是,您无法模拟本机打开文件对话框的行为
  • 您只想设置上传输入元素的样式吗?这样它就没有默认外观,但是例如按钮的外观?
  • 没有人知道如何在不使用 type="file" 的情况下打开对话框吗?只是直接的javascript。

标签: javascript jquery html


【解决方案1】:

即用型函数(使用 Promise)

/**
 * Select file(s).
 * @param {String} contentType The content type of files you wish to select. For instance, use "image/*" to select all types of images.
 * @param {Boolean} multiple Indicates if the user can select multiple files.
 * @returns {Promise<File|File[]>} A promise of a file or array of files in case the multiple parameter is true.
 */
function selectFile(contentType, multiple){
    return new Promise(resolve => {
        let input = document.createElement('input');
        input.type = 'file';
        input.multiple = multiple;
        input.accept = contentType;

        input.onchange = () => {
            let files = Array.from(input.files);
            if (multiple)
                resolve(files);
            else
                resolve(files[0]);
        };

        input.click();
    });
}

在这里试试

// Content wrapper element
let contentElement = document.getElementById("content");

// Button callback
async function onButtonClicked(){
    let files = await selectFile("image/*", true);
    contentElement.innerHTML = files.map(file => `<img src="${URL.createObjectURL(file)}" style="width: 100px; height: 100px;">`).join('');
}

// ---- function definition ----
function selectFile (contentType, multiple){
    return new Promise(resolve => {
        let input = document.createElement('input');
        input.type = 'file';
        input.multiple = multiple;
        input.accept = contentType;

        input.onchange = _ => {
            let files = Array.from(input.files);
            if (multiple)
                resolve(files);
            else
                resolve(files[0]);
        };

        input.click();
    });
}
<button onclick="onButtonClicked()">Select images</button>
<div id="content"></div>

【讨论】:

  • 如果你只是关闭对话框而不选择任何文件解析永远不会调用并且代码流挂起。
  • Javascript 没有数组的first 方法。
  • 可以通过添加一些关于您的答案如何工作的解释来改进此答案。
【解决方案2】:

function promptFile(contentType, multiple) {
  var input = document.createElement("input");
  input.type = "file";
  input.multiple = multiple;
  input.accept = contentType;
  return new Promise(function(resolve) {
    document.activeElement.onfocus = function() {
      document.activeElement.onfocus = null;
      setTimeout(resolve, 500);
    };
    input.onchange = function() {
      var files = Array.from(input.files);
      if (multiple)
        return resolve(files);
      resolve(files[0]);
    };
    input.click();
  });
}
function promptFilename() {
  promptFile().then(function(file) {
    document.querySelector("span").innerText = file && file.name || "no file selected";
  });
}
<button onclick="promptFilename()">Open</button>
<span></span>

【讨论】:

    【解决方案3】:

    使用 jQuery

    ​​>

    我会像这样创建一个按钮和一个不可见的输入:

    <button id="button">Open</button>
    <input id="file-input" type="file" name="name" style="display: none;" />
    

    并添加一些 jQuery 来触发它:

    $('#button').on('click', function() {
        $('#file-input').trigger('click');
    });
    

    使用 Vanilla JS

    同样的想法,没有 jQuery(感谢@Pascale):

    <button onclick="document.getElementById('file-input').click();">Open</button>
    <input id="file-input" type="file" name="name" style="display: none;" />
    

    【讨论】:

    • 这比让输入字段透明更优雅的解决方案
    • 我使用了相同的技术(在纯 js 中:form.file_selector.click();),其中 file_selector 是动态添加的文件输入(由 innerHTML 添加)。但它不起作用。请问有什么帮助或建议吗?
    • @Ron van der Heijden 谢谢你,我想我知道为什么它不起作用(现在它仍然起作用了)。对于那些可能有类似问题的人,如果出于安全原因,事件不会触发,除非它在用户事件(单击左右)之后调用,否则可能是原因。我想在 ajax 请求之后(在函数内部)触发事件。
    • 非常感谢 Vanilla JS 示例!
    • vanilla js 解决方案非常适合我。非常感谢。
    【解决方案4】:

    带有jquery库

    <button onclick="$('.inputFile').click();">Select File ...</button>
    <input class="inputFile" type="file" style="display: none;">
    

    【讨论】:

    • 您好!虽然这段代码可以解决问题,including an explanation 解决问题的方式和原因确实有助于提高帖子的质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请edit您的回答添加解释并说明适用的限制和假设。
    【解决方案5】:

    仅在 HTML 中:

    <label>
      <input type="file" name="input-name" style="display: none;" />
      <span>Select file</span>
    </label>
    

    编辑:我没有在 Blink 中测试过,它实际上不适用于 &lt;button&gt;,但它应该适用于大多数其他元素——至少在最近的浏览器中。 p>

    用上面的代码检查this fiddle

    【讨论】:

      【解决方案6】:

      扩展“levi”的答案并展示如何从上传中获取响应,以便您可以处理文件上传:

      selectFile(event) {
          event.preventDefault();
      
          file_input = document.createElement('input');
          file_input.addEventListener("change", uploadFile, false);
          file_input.type = 'file';
          file_input.click();
      },
      
      uploadFile() {
          let dataArray = new FormData();
          dataArray.append('file', file_input.files[0]);
      
          // Obviously, you can substitute with JQuery or whatever
          axios.post('/your_super_special_url', dataArray).then(function() {
              //
          });
      }
      

      【讨论】:

        【解决方案7】:

        首先声明一个变量来存储文件名(以便以后使用):

        var myfiles = [];
        

        打开文件对话框

        $('#browseBtn').click(function() {
            $('<input type="file" multiple>').on('change', function () {
                myfiles = this.files; //save selected files to the array
                console.log(myfiles); //show them on console
            }).click();
        });
        

        我正在发布它,因此它可能会对某人有所帮助,因为互联网上没有关于如何将文件名存储到数组中的明确说明!

        【讨论】:

          【解决方案8】:

          仅 JS - 不需要 jquery

          ​​>

          只需创建一个输入元素并触发点击。

          var input = document.createElement('input');
          input.type = 'file';
          input.click();
          

          这是最基本的,弹出一个选择文件对话框,但如果不处理所选文件,它就没有任何用处...

          处理文件

          onchange 事件添加到新创建的输入将允许我们在用户选择文件后执行操作。

          var input = document.createElement('input');
          input.type = 'file';
          
          input.onchange = e => { 
             var file = e.target.files[0]; 
          }
          
          input.click();
          

          目前我们有存储各种信息的文件变量:

          file.name // the file's name including extension
          file.size // the size in bytes
          file.type // file type ex. 'application/pdf'
          

          太棒了!

          但是,如果我们需要文件的内容呢?

          为了获取文件的实际内容,出于各种原因。放置图像,加载到画布中,使用 Base64 数据 url 创建一个窗口等。我们需要使用 FileReader API

          我们将创建一个 FileReader 的实例,并将我们用户选择的文件引用加载到它。

          var input = document.createElement('input');
          input.type = 'file';
          
          input.onchange = e => { 
          
             // getting a hold of the file reference
             var file = e.target.files[0]; 
          
             // setting up the reader
             var reader = new FileReader();
             reader.readAsText(file,'UTF-8');
          
             // here we tell the reader what to do when it's done reading...
             reader.onload = readerEvent => {
                var content = readerEvent.target.result; // this is the content!
                console.log( content );
             }
          
          }
          
          input.click();
          

          尝试将上述代码粘贴到您的开发工具的控制台窗口中,它应该会产生一个选择文件对话框,选择文件后,控制台现在应该打印文件的内容。

          示例 - “Stackoverflow 的新背景图片!”

          让我们尝试创建一个文件选择对话框来将 stackoverflows 背景图像更改为更辣的...

          var input = document.createElement('input');
          input.type = 'file';
          
          input.onchange = e => { 
          
             // getting a hold of the file reference
             var file = e.target.files[0]; 
          
             // setting up the reader
             var reader = new FileReader();
             reader.readAsDataURL(file); // this is reading as data url
          
             // here we tell the reader what to do when it's done reading...
             reader.onload = readerEvent => {
                var content = readerEvent.target.result; // this is the content!
                document.querySelector('#content').style.backgroundImage = 'url('+ content +')';
             }
          
          }
          
          input.click();
          

          打开devtools,将上面的代码粘贴到控制台窗口,这应该会弹出一个选择文件对话框,在选择图像时,stackoverflows内容框背景应该会变为所选图像。

          干杯!

          【讨论】:

          • 虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!
          • 优秀。但是我很难在 Safari iOS 上使用它。 onchange 事件没有触发。
          • 访问文件的方法见这里:developer.mozilla.org/en-US/docs/…document.getElementById('input').files[0];
          • 当我使用建议的代码时,我得到了以下错误:File chooser dialog can only be shown with a user activation.我该如何解决这个问题?
          • @Paul File chooser dialog can only be shown with a user activation. 基本上,这意味着它只有在用户点击某些东西时才会打开。尝试这样的事情:document.body.onclick = openFileFunction。当您点击该网页时,它现在应该可以正常打开了。
          【解决方案9】:

          为了完整起见,Ron van der Heijden's solution 在纯 JavaScript 中:

          <button onclick="document.querySelector('.inputFile').click();">Select File ...</button>
          <input class="inputFile" type="file" style="display: none;">
          

          【讨论】:

            猜你喜欢
            • 2011-08-30
            • 1970-01-01
            • 2017-10-05
            • 2023-04-08
            • 1970-01-01
            • 2012-03-02
            • 2018-01-12
            • 1970-01-01
            • 2014-07-13
            相关资源
            最近更新 更多