【问题标题】:JavaScript 'input multiple' file duplicationJavaScript“输入多个”文件重复
【发布时间】:2013-02-06 10:08:20
【问题描述】:

这是我的代码:

        var rowData = [];

        var showFiles = function () {
            var input = document.getElementById('doc-upload');
            if (input.files.length > 0) {
                for (var i = 0; i < input.files.length; i += 1) {
                    rowData.push([input.files[i].name]);
                };
                console.log(rowData);
            };
        };
        document.getElementById('doc-upload').addEventListener('change', showFiles, this);

'rowData' 在我第一次上传某些东西时接收到一个正常值。 在第二次尝试时,它开始复制传入的值。

如果我先上传了 1 个文件,试试就可以了。 第二次我会得到 2 个相同的文件。 第三个 4 个文件,exetera。

为什么会这样?

更新:

更多解释: 发生了什么:我上传 x.doc 我的数组是 [x.doc],现在我想上传 y.doc。我选择y.doc,我的数组变成[x.doc,y.doc,y.doc],然后我上传z.doc,aaray看起来像[x.doc,y.doc,y.doc,z。 doc、z.doc、z.doc、z.doc]。等等。它必须对长度属性做一些事情,我把它搞砸了。

UPD2:

现在是完整版代码:

    //file upload
    var rowData = [];
    docAddButton.addListener('click', function () {
        var showFiles = function () {
            var input = document.getElementById('doc-upload');
            if (input.files.length > 0) {
                for (var i = 0; i < input.files.length; i += 1) {
                    if (rowData.indexOf(true, input.files[i].name, Math.round(input.files[i].size * 0.001) + ' кб') === -1) {
                        rowData.push([
                            true,
                            input.files[i].name, 
                            Math.round(input.files[i].size * 0.001) + ' кб'
                        ]);
                    }
                }
                console.log(rowData);
                tableModel.setData(rowData);
            };
        };
        document.getElementById('doc-upload').addEventListener('change', showFiles, this);
    });

感谢所有帮助过的人!

解决方案: 您可以从 UPD2 中看到我在 eventListener 'click' 中有我的函数。发生的事情是,每次我按下输入按钮时,它都会收到额外的“更改”侦听器。

我将用于输入的 .addListener 更改为 .addListenerOnce。

【问题讨论】:

  • "rowData.push([input.files[i].name]);" 为什么要将文件名作为 array 推送?我预计只有rowData.push(input.files[i].name);(没有[] 大约input.files[i].name)。
  • 这是由于我使用的数组结构。 rowData 用于设置表格的模型,数组是表格的一行。我推送的每个下一个数组都将是表中的下一行。 [input.files[i].name] 中的每个元素都将是下一列。例如 [input.files[i].name, input.files[i].size]。我只是剪掉了这些东西来在这里显示代码。

标签: javascript arrays file input


【解决方案1】:

大概您没有重新加载页面,也没有清除rowData。您尚未显示定义rowData 的方式/位置,但看起来它的相同实例在对showFiles 的调用之间被重用。 (如果你没有在任何地方声明它,你就会成为The Horror of Implicit Globals 的牺牲品。)


从下面的 cmets 中,听起来您想保留 rowData 中的条目,但您只想添加 条目。如果是这样,您将需要明确检查:

var showFiles = function () {
    var input, i, file;

    input = document.getElementById('doc-upload');
    for (i = 0; i < input.files.length; i += 1) {
        file = input.files[i].name;
        if (indexOfFile(rowData, file) === -1) {
            rowData.push([file]);
        }
    };
    console.log(rowData);
};

function indexOfFile(data, file) {
    var index;

    for (index = 0; index < data.length; ++index) {
        // Note that the 0 may need to be changed if the
        // `rowData.push([file])` line above doesn't put
        // the filename at index 0
        if (data[index][0] === file) {
            return index;
        }
    }
    return -1;
}

旁注:您已经说过,您推送数组而不仅仅是文件名的原因是您还包括在该数组中的其他信息,但您将其排除在您的问题之外。这很好,但它可能很微妙,请参阅上面关于索引0 的说明。您可以考虑改用对象数组:

rowData.push({
    file: file,
    other: "info",
    goes: "here"
});

...然后在indexOfFile:

if (data[index].file === file) {

这样,如果您更改所推送的内容的结构,代码就不太容易被破坏。

【讨论】:

  • 我把它声明在'var rowData = [];'的正上方我在代码中使用层来为我的表模型设置数据。 (qooxdoo)
  • @user1869429:那就是问题所在,每次调用showFiles 时都会重复使用一个实例。要么声明它 showFiles 或将rowData = []; 放在showFiles 的开头以在添加新信息之前删除旧信息。
  • Crowde:我真的做不到。如果我每次都能清除它。我的用户只会看到他们上次“更改”上传的文件。但是可能希望将几个文件上传到同一个数组中。
  • 你是对的。如果我在每次更改之前清除数组,我想它会正常工作。只是我不想清除数组。但我最终可能会在“showFiles”函数中分离数组。
  • @user1869429:我仍然不能 100% 确定我理解你在做什么,但如果你不能清除它但你不想重复,唯一的办法就是检查您要添加的项目是否已经存在,如果不存在则仅添加它。我已经用一个这样做的例子更新了答案。
【解决方案2】:

基本上,

rowData.push()

只会继续将元素附加到变量的末尾。您需要检查这些输入是否已经存在。

(编辑-)

试试这个:-

        rowData=[];
        var showFiles = function () {
        var input = document.getElementById('doc-upload');
        if (input.files.length > 0) {
            for (var i = 0; i < input.files.length; i += 1) {
              var f=[];
              for(var j=0;j<rowData.length;j++)
                 f.push(rowData[j][0]);
              if(f.indexOf(input.files[i].name) == -1)
                  rowData.push([input.files[i].name]);
            }
            console.log(rowData);
        };
    };
    document.getElementById('doc-upload').addEventListener('change', showFiles, this);

【讨论】:

  • 不,不是这样。在我将它们推入“rowData”后,我将其显示给用户。用户可能想要几个类似的文件。发生了什么:我上传 x.doc 我的数组是 [x.doc],现在我想上传 y.doc。我选择y.doc,我的数组变成[x.doc,y.doc,y.doc],然后我上传z.doc,aaray看起来像[x.doc,y.doc,y.doc,z。 doc、z.doc、z.doc、z.doc]。等等。它必须对长度属性做一些事情,我把它搞砸了。
  • 你试过我给的代码了吗?这实际上检查了数组中的多个文件名。您之前的评论表明您正在多次重用推送 API。
  • 我做到了。它的作用相同。这是界面截图link
  • 另外,如果您不确定 EXTRA 元素是从代码中的哪个位置添加的,您可以为 rowData 的推送创建一个通用函数并从所有其他位置调用它。检查 if(rowData.indexOf(input.files[i].name) == -1) 将确保它们只添加一次。
  • 我注意到您将数组推送到变量而不是普通的文件名字符串。希望您确实相应地修改了检查条件。
猜你喜欢
  • 2017-08-11
  • 1970-01-01
  • 2018-02-13
  • 1970-01-01
  • 2021-09-12
  • 1970-01-01
  • 2013-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多