即使选择了文件,Javascript <input type =“file”/>也有空文件列表

时间:2015-07-15 22:31:18

标签: javascript html file-upload

我尝试在HTML和Javascript中进行简单的文件上传。

我设置它的方式是让<input type="file" id="file-upload-input"/>订阅loadFile事件的onChange函数。 (因为它看起来很糟糕,我有input隐形。)

然后我有一个<button/>函数handleBrowseClick订阅了它的onclick事件。

上述两个控件似乎都运行正常:当我点击<button/>时,会调用handleBrowseClick,点击我的<input type="file">,导致文件对话框打开。但是,一旦我选择了一个文件并按下&#34;打开&#34;在对话框中(触发<input type="file">的{​​{1}}事件,从而调用我的onChange函数。

正如您在Javascript中看到的那样,此时尝试通过获取loadFile,访问其<input type="file">属性并尝试获取该数组的第一个元素来读取该文件,以便我可以用files读取它(它工作正常)。

但是,无论我选择哪个文件,FileReader数组始终为空(因此我的files打印出alert)!在经过大量调试并缩小问题范围之后,我发现在"# Files Selected: 0"中,如果我删除稍微修改HTML主体的调试代码,那么文件上传突然完美无缺! (handleBrowseClick()打印出alert。)

所以这就是我的问题:为什么会有一条

  • 仅修改HTML的正文(但不会影响任何控件)
  • 与文件上传功能
  • 无关

阻止我的文件上传工作?

&#13;
&#13;
"# Files Selected: 1"
&#13;
function handleBrowseClick()
{
    document.getElementById("upload-file-input").click();
    // if I comment out this line, then the file upload works
    document.body.innerHTML += "<br/>Browsing...";
}
function loadFile()
{
    var elem = document.getElementById("upload-file-input");
    var files = elem.files;
    alert("# Files Selected: " + files.length);
    var file = files[0];
    if (!file) return;
    
    var reader = new FileReader();
    reader.onload = function()
    {
	// do stuff with reader.result
	// example:
	document.getElementById("file-content").innerHTML = reader.result;
    };
    reader.readAsText(file);
}
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

使用innerHTML +=解释HTML,它不仅会添加一些文本,而是删除所有内容并重新创建整个HTML。见https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML

  

因此,建议您在使用innerHTML时不要使用   插入纯文本;相反,使用node.textContent。事实并非如此   将传递的内容解释为HTML,而是将其作为原始内容插入   文本。

因此,在您调用之前,input元素与之后的元素不同。您可以在下面的jsfiddle中看到,比较调用之前和之后的节点,当您使用innerHTML +=时,您将看到它不是相同的元素,即使HTML是相同的。

http://jsfiddle.net/6nja0v6b/1/

修改

原始答案中的引用可能导致混淆,而它描述了innerHTML的作用,上下文不是问题之一。可以在此处找到更精确的描述:https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-innerHTML。特别是:

  

元素。 innerHTML [= value]

     

返回表示元素的HTML或XML片段   内容。

     

可以设置,用解析的节点替换元素的内容   来自给定的字符串。

  

在设置时,必须运行以下步骤:

     

让片段成为调用片段解析算法的结果   将新值作为标记,将上下文对象作为上下文   元件。将所有内容替换为上下文对象中的片段。

通过在eventListener上添加node,然后调用innerHTML在该节点上插入完全相同的HTML,可以非常简单地说明这一点。虽然文档看起来相同,但行为不一致,因为innerHTML重新创建节点结构,innerHTML调用之前的节点与之后的节点不同。请参阅代码段:

var container = document.querySelector("#container");
var testElem = document.querySelector("#testElement");
var replaceBtn = document.querySelector("#replaceHtml");
var compareBtn = document.querySelector("#compare");

//We add the listener on original testElem
testElement.addEventListener('click', function(e) {
  alert("eventListener is working");
})

//After using innerHTML, event listener won't work and compare will be false
replaceBtn.onclick = function() {
  //This doesn't change the HTML, but replaces the node
  container.innerHTML = container.innerHTML;
}

//Use this to compare original testElement to new one. After innerHTML is used, it's not the same node.
compare.onclick = function() {
  alert("Is testElem \=\=\= document.querySelector(\"testElement\"): " + (testElem === document.querySelector("#testElement")));
}
#testElement {
  width: 100px;
  height: 100px;
  background-color: blue;
}
<div id="container">
  <div id="testElement"></div>
</div>
<button id="replaceHtml">Replace HTML</button>
<button id="compare">Compare nodes</button>