我有一个表单,让用户添加最多 5 个文件,但我只显示一个
<input type="file">
,如果用户确实在 <input>
处放置了一个文件,那么我会更新表单添加另一个输入,所以在。 当我使用文件选择器并选择一个文件时,效果非常好。但现在我尝试添加一个选项,以便用户只需 CTRL+V 将图像剪贴板内容直接放入 <input>
字段,然后如前所述更新表格。我还添加了一个循环,验证输入字段是否确实有内容,以便用户不会更新,例如第 0 个输入,然后不必要地出现新输入。这就是让我的代码失败的一点,如下所示:
编辑我刚刚添加了一个模拟问题的完整 HTML 文件:
编辑2这个问题在基于Chromium的Brave浏览器下没有发生,我可以在Firefox下模拟它
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<title>Document</title>
</head>
<body>
<form class="form-post" role="form" method="POST" enctype="multipart/form-data" action="/someroute">
<!-- other inputs... -->
<div id="form-post-file-input-div">
<div class="form-post-file-input-box">
<input class="novo-post-form-item form-post-file-input" name="arquivos[]" type="file" onchange="addNovoInputFile(this, 5)">
</div>
</div>
</form>
<script>
var addNovoInputFile = function(elem, max){
fileInputs = $('.form-post-file-input');
// When this loop is reached from a copypaste event, the content of fileInputs[0].files is empty
// this doesn't happen when I just select a file from filepicker
for(var i=0; i < fileInputs.length; i++)
{
if(fileInputs[i].files.length === 0)
return;
}
// I put this loop so I don't update the form in case, for example, if the user keeps updating a file at the 0th <input>
// but maybe my solution is just changing the logic of this loop
if(fileInputs.length >= max || elem.files.length === 0)
return;
var novoInput = "<div class=\"form-post-file-input-box\">";
novoInput += "<input class=\"novo-post-form-item form-post-file-input\" name=\"arquivos[]\" type=\"file\" onchange=\"addNovoInputFile(this, " + max + ")\">";
novoInput += "</div>"
$(novoInput).appendTo(".form-post #form-post-file-input-div");
};
// New event I just added in order to fill the input with a printscreen content in the clipboard
window.addEventListener('paste', e => {
let inputs = document.getElementsByName('arquivos[]');
let inputToChange = inputs[inputs.length-1];
if(e.clipboardData.files.length > 0){
inputToChange.files = e.clipboardData.files;
addNovoInputFile(inputToChange, 5);
}
});
</script>
</body>
</html>
到底发生的事情是,当我第二次运行 CTRL+V
0th element
返回的列表中的 $('.form-post-file-input')
的 .files
数组为空,并且 1st
包含剪贴板中的内容。为什么会发生这种情况,因为当我第一次输入CTRL+V时,我确实填写了.files
的内容(在addEventListener
中),证明是当我submit
表单0th
时文件已上传到服务器...但是 .files
是空的...我不明白为什么特别是因为当我从文件选择器中选择文件时不会发生这种情况。
原因是使用
return;
语句将退出整个函数而不是 for 循环,因此它不会创建另一个输入选择器。
您必须使用 break;
来代替:
// When this loop is reached from a copypaste event, the content of fileInputs[0].files is empty
// this doesn't happen when I just select a file from filepicker
for(var i=0; i < fileInputs.length; i++)
{
if(fileInputs[i].files.length === 0)
return;
}
到
// When this loop is reached from a copypaste event, the content of fileInputs[0].files is empty
// this doesn't happen when I just select a file from filepicker
for(var i=0; i < fileInputs.length; i++)
{
if(fileInputs[i].files.length === 0)
break; // Change
}