如何主动唤起文件选择框

如题,搞过文件上传的,肯定会有这种想法,初学者尝试这样使用

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

像我这样经验老道的,一看,“不可能,这会受到浏览器安全策略限制”,牛逼哄哄的祭出正解

solution

input[type=file]飘在点击区上方,老手的惯用伎俩,这就叫“经验”,但最近一些事,让我啪啪打脸,我的人生观被颠覆了,不信你试试在 Chrome 的 Console 中试一下。

让你在Chrome中试,是因为目前好像只有Chrome能这么大胆的放开,让你这么放肆。

我们再尝试在Safari下试一下。。。

好像没效果,我们可联想到,浏览器限制这些东西,无非是想确定是人为操作,而非自动运行,在很多类似的情形,都有个要求“人为事件发生时”,比如用户点击、键盘敲击。我们可以这么尝试一下

<input id="file" type="file" style="display:none" />  
<button id="trigger">选择</button>

<script>  
let input = document.getElementById('file');

document.getElementById('trigger').onclick = function () {  
  input.click();
};
</script>  

这种情况很适合,“原生的input的太丑,我想弄个漂亮的按钮触发上传”、“我想更优雅的控制上传”

还有一种情况我想在输入域中输入某个命令,回车触发上传

<input id="file" type="file" style="display:none" />  
<div id="trigget" contenteditable>敲击回车触发上传</div>  
<script>  
let input = document.getElementById('file');

document.getElementById('trigger').onkeypress = function (e) {  
  e.preventDefault();
  input.click();
};
</script>  

浏览器兼容性如下

compatible

可以说是全兼容

有些版本我懒得测了,但我想连IE8都行,其它的不用测了吧
IE 下,input[type=file]需要存在文档流中

至此,我想你之前经历过的,input飘在某个按钮上这种别扭设计可以扔掉了,但是还没完,不知道大家想到 labelFor 没有,如果只是想点击事件转移,我们尝试以下方案

<input id="file" type="file" style="display:none" />  
<label for="file">  
  <span>点击上传</span>
</label>  

这种方式,属于html原生支持的、设计如此的,不需要一句js脚本,适用于简单朴素的原生表单。