【问题标题】:Removing file from multiple files uploader on button click when using HTML5 file input使用 HTML5 文件输入时单击按钮从多个文件上传器中删除文件
【发布时间】:2015-11-10 19:51:15
【问题描述】:

如何在此处添加 remove 按钮,就像这样在文件队列中一个一个地简单地删除

我不使用带有OOB插件的免费文件上传插件的原因是因为我的客户要求是出于安全目的,他们需要简单的上传ui而不需要任何复杂的插件。

$(function() {
  var dropZoneId = "drop-zone";
  var buttonId = "clickHere";
  var mouseOverClass = "mouse-over";

  var dropZone = $("#" + dropZoneId);
  var ooleft = dropZone.offset().left;
  var ooright = dropZone.outerWidth() + ooleft;
  var ootop = dropZone.offset().top;
  var oobottom = dropZone.outerHeight() + ootop;
  var inputFile = dropZone.find("input");
  document.getElementById(dropZoneId).addEventListener("dragover", function(e) {
    e.preventDefault();
    e.stopPropagation();
    dropZone.addClass(mouseOverClass);
    var x = e.pageX;
    var y = e.pageY;

    if (!(x < ooleft || x > ooright || y < ootop || y > oobottom)) {
      inputFile.offset({
        top: y - 15,
        left: x - 100
      });
    } else {
      inputFile.offset({
        top: -400,
        left: -400
      });
    }

  }, true);

  if (buttonId != "") {
    var clickZone = $("#" + buttonId);

    var oleft = clickZone.offset().left;
    var oright = clickZone.outerWidth() + oleft;
    var otop = clickZone.offset().top;
    var obottom = clickZone.outerHeight() + otop;

    $("#" + buttonId).mousemove(function(e) {
      var x = e.pageX;
      var y = e.pageY;
      if (!(x < oleft || x > oright || y < otop || y > obottom)) {
        inputFile.offset({
          top: y - 15,
          left: x - 160
        });
      } else {
        inputFile.offset({
          top: -400,
          left: -400
        });
      }
    });
  }

  document.getElementById(dropZoneId).addEventListener("drop", function(e) {
    $("#" + dropZoneId).removeClass(mouseOverClass);
  }, true);

  inputFile.on('change', function(e) {
    $('#filename').html("");
    var fileNum = this.files.length,
      initial = 0,
      counter = 0;
    for (initial; initial < fileNum; initial++) {
      counter = counter + 1;
      $('#filename').append('<span class="fa-stack fa-lg"><i class="fa fa-file fa-stack-1x "></i><strong class="fa-stack-1x" style="color:#FFF; font-size:12px; margin-top:2px;">' + counter + '</strong></span> ' + this.files[initial].name + '&nbsp;&nbsp;<span class="fa fa-times-circle fa-lg closeBtn" title="remove"></span><br>');
    }
  });

})
#drop-zone {
  width: 100%;
  min-height: 150px;
  border: 3px dashed rgba(0, 0, 0, .3);
  border-radius: 5px;
  font-family: Arial;
  text-align: center;
  position: relative;
  font-size: 20px;
  color: #7E7E7E;
}
#drop-zone input {
  position: absolute;
  cursor: pointer;
  left: 0px;
  top: 0px;
  opacity: 0;
}
/*Important*/

#drop-zone.mouse-over {
  border: 3px dashed rgba(0, 0, 0, .3);
  color: #7E7E7E;
}
/*If you dont want the button*/

#clickHere {
  display: inline-block;
  cursor: pointer;
  color: white;
  font-size: 17px;
  width: 150px;
  border-radius: 4px;
  background-color: #4679BD;
  padding: 10px;
}
#clickHere:hover {
  background-color: #376199;
}
#filename {
  margin-top: 10px;
  margin-bottom: 10px;
  font-size: 14px;
  line-height: 1.5em;
}
.file-preview {
  background: #ccc;
  border: 5px solid #fff;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
  display: inline-block;
  width: 60px;
  height: 60px;
  text-align: center;
  font-size: 14px;
  margin-top: 5px;
}
.closeBtn:hover {
  color: red;
}
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="drop-zone">
  <p>Drop files here...</p>
  <div id="clickHere">or click here.. <i class="fa fa-upload"></i>
    <input type="file" name="file" id="file" multiple />
  </div>
  <div id='filename'></div>
</div>

注意:我不拥有代码,我已将其用作其他人的资源并为我的客户进行了修改

**更新 这是我的fiddle链接

【问题讨论】:

标签: jquery html multifile-uploader


【解决方案1】:

HTML5 文件输入的文件列表是只读的,因此当试图从中删除文件时,您将不被允许。

您需要做的是维护一个单独的数组列表(如示例中的 JSON 数组)。

我已经用一个 div 包裹了您的 X 按钮,该 div 包含连接到“file_”字符串的文件索引,并添加了一个 onclick 函数 removeLine(obj) 接受该元素作为对象。

我还在全局范围内添加了一个 JSON 数组 finalFiles,并将 inputFile 移动到了全局范围内。

当文件输入发生变化时,我通过以下方式设置带有所选文件的 JSON 数组:

$.each(this.files,function(idx,elm){
           finalFiles[idx]=elm;
        });

函数removeLine将刷新输入文件列表以允许再次选择相同的文件如果用户错误地删除了文件,该函数从包装器分区id中获取文件索引,删除包装器div然后删除文件来自 JSON 数组。

function removeLine(obj)
    {
      inputFile.val('');
      var jqObj = $(obj);
      var container = jqObj.closest('div');
      var index = container.attr("id").split('_')[1];
      container.remove(); 

      delete finalFiles[index];
      //console.log(finalFiles);
    }

您可以在表单提交时维护您的文件,并使用 FormData 以类似于This Article 的方式通过 AJAX 发布它们。

var dropZoneId = "drop-zone";
  var buttonId = "clickHere";
  var mouseOverClass = "mouse-over";
var dropZone = $("#" + dropZoneId);
 var inputFile = dropZone.find("input");
 var finalFiles = {};
$(function() {
  

  
  var ooleft = dropZone.offset().left;
  var ooright = dropZone.outerWidth() + ooleft;
  var ootop = dropZone.offset().top;
  var oobottom = dropZone.outerHeight() + ootop;
 
  document.getElementById(dropZoneId).addEventListener("dragover", function(e) {
    e.preventDefault();
    e.stopPropagation();
    dropZone.addClass(mouseOverClass);
    var x = e.pageX;
    var y = e.pageY;

    if (!(x < ooleft || x > ooright || y < ootop || y > oobottom)) {
      inputFile.offset({
        top: y - 15,
        left: x - 100
      });
    } else {
      inputFile.offset({
        top: -400,
        left: -400
      });
    }

  }, true);

  if (buttonId != "") {
    var clickZone = $("#" + buttonId);

    var oleft = clickZone.offset().left;
    var oright = clickZone.outerWidth() + oleft;
    var otop = clickZone.offset().top;
    var obottom = clickZone.outerHeight() + otop;

    $("#" + buttonId).mousemove(function(e) {
      var x = e.pageX;
      var y = e.pageY;
      if (!(x < oleft || x > oright || y < otop || y > obottom)) {
        inputFile.offset({
          top: y - 15,
          left: x - 160
        });
      } else {
        inputFile.offset({
          top: -400,
          left: -400
        });
      }
    });
  }

  document.getElementById(dropZoneId).addEventListener("drop", function(e) {
    $("#" + dropZoneId).removeClass(mouseOverClass);
  }, true);


  inputFile.on('change', function(e) {
    finalFiles = {};
    $('#filename').html("");
    var fileNum = this.files.length,
      initial = 0,
      counter = 0;

    $.each(this.files,function(idx,elm){
       finalFiles[idx]=elm;
    });

    for (initial; initial < fileNum; initial++) {
      counter = counter + 1;
      $('#filename').append('<div id="file_'+ initial +'"><span class="fa-stack fa-lg"><i class="fa fa-file fa-stack-1x "></i><strong class="fa-stack-1x" style="color:#FFF; font-size:12px; margin-top:2px;">' + counter + '</strong></span> ' + this.files[initial].name + '&nbsp;&nbsp;<span class="fa fa-times-circle fa-lg closeBtn" onclick="removeLine(this)" title="remove"></span></div>');
    }
  });



})

function removeLine(obj)
{
  inputFile.val('');
  var jqObj = $(obj);
  var container = jqObj.closest('div');
  var index = container.attr("id").split('_')[1];
  container.remove(); 

  delete finalFiles[index];
  //console.log(finalFiles);
}
#drop-zone {
  width: 100%;
  min-height: 150px;
  border: 3px dashed rgba(0, 0, 0, .3);
  border-radius: 5px;
  font-family: Arial;
  text-align: center;
  position: relative;
  font-size: 20px;
  color: #7E7E7E;
}
#drop-zone input {
  position: absolute;
  cursor: pointer;
  left: 0px;
  top: 0px;
  opacity: 0;
}
/*Important*/

#drop-zone.mouse-over {
  border: 3px dashed rgba(0, 0, 0, .3);
  color: #7E7E7E;
}
/*If you dont want the button*/

#clickHere {
  display: inline-block;
  cursor: pointer;
  color: white;
  font-size: 17px;
  width: 150px;
  border-radius: 4px;
  background-color: #4679BD;
  padding: 10px;
}
#clickHere:hover {
  background-color: #376199;
}
#filename {
  margin-top: 10px;
  margin-bottom: 10px;
  font-size: 14px;
  line-height: 1.5em;
}
.file-preview {
  background: #ccc;
  border: 5px solid #fff;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
  display: inline-block;
  width: 60px;
  height: 60px;
  text-align: center;
  font-size: 14px;
  margin-top: 5px;
}
.closeBtn:hover {
  color: red;
  display:inline-block;
}
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="drop-zone">
  <p>Drop files here...</p>
  <div id="clickHere">or click here.. <i class="fa fa-upload"></i>
    <input type="file" name="file" id="file" multiple />
  </div>
  <div id='filename'></div>
</div>

【讨论】:

  • 谢谢@KAD 我会试试这个。
  • 你的工作几乎完美了一件可以完美的事情,当你导入多个文件然后删除组中的一个文件,这只是你的目标文件,元素中的所有文件也会删除,你可以看到顺便说一句,如果您删除 css #drop-zone input 的部分,文件元素再次感谢。
  • 如何提交?
  • 你提交文件时是否使用了formdata?
  • 你好。我有一个问题。当我通过单击关闭图标从列表中删除一个文件时,表单将发送那些保留在列表中的文件?
【解决方案2】:

我以前为我的 Dropzone 做过这个。随意调整。这是来自我的 Laravel 应用程序。你应该关注avatar_refresh_upload。剪掉不必要的东西,你就完成了。

function avatar_refresh_upload() {
    var input = $('input#avatar[type=file]');

    input.replaceWith(input.val('').clone(true));

    $('#selected_file').html('{{ Lang::get('app.profile_avatar_select') }}');
    $('#avatar_refresh_upload').removeAttr('style');
}

$(document).ready(function ($) {

    $('input:file#avatar').change(function () {
        var file_name = $(this).val();
        if (file_name.length > 10) {
            file_name = file_name.substring(0, 10) + '...';
        }
        $('#selected_file').html('File "' + file_name + '" chosen');
        $('#avatar_refresh_upload').css('display', 'inline-block');
    });

    $('#avatar_refresh_upload').on('click', function () {
        avatar_refresh_upload();
    });

    @if ($user->avatar != '')
    $('#remove_avatar').change(function () {

        if ($(this).is(':checked')) {

            avatar_refresh_upload();
            $('#avatar').prop('disabled', true);
            $('#avatar_preview').css('opacity', '0.5');
            $('#avatar_upload_form_area').css('opacity', '0.5');
            $('#remove_avatar_info').show();

        } else {

            $('#avatar').prop('disabled', false);
            $('#avatar_preview').removeAttr('style');
            $('#avatar_upload_form_area').removeAttr('style');
            $('#remove_avatar_info').removeAttr('style');

        }
    });
    @endif

});

长话短说 - 如果您想在选择要上传的文件之后但在提交之前重置输入文件,则必须运行

input.replaceWith(input.val('').clone(true));

【讨论】:

  • 好的,我会试试这个谢谢@slick
【解决方案3】:

由于我们无法修改 &lt;input type'file' multiple&gt; 标记中的选定文件数组,因此我已更新您的代码以显示文件数并在选择多个文件时删除所有文件。

updated code 有一个小提琴。

$(function () {
    var dropZoneId = "drop-zone";
    var buttonId = "clickHere";
    var mouseOverClass = "mouse-over";

    var dropZone = $("#" + dropZoneId);
    var ooleft = dropZone.offset().left;
    var ooright = dropZone.outerWidth() + ooleft;
    var ootop = dropZone.offset().top;
    var oobottom = dropZone.outerHeight() + ootop;
    var inputFile = dropZone.find("input");
    document.getElementById(dropZoneId).addEventListener("dragover", function (e) {
        e.preventDefault();
        e.stopPropagation();
        dropZone.addClass(mouseOverClass);
        var x = e.pageX;
        var y = e.pageY;

        if (!(x < ooleft || x > ooright || y < ootop || y > oobottom)) {
            inputFile.offset({
                top: y - 15,
                left: x - 100
            });
        } else {
            inputFile.offset({
                top: -400,
                left: -400
            });
        }

    }, true);

    if (buttonId != "") {
        var clickZone = $("#" + buttonId);

        var oleft = clickZone.offset().left;
        var oright = clickZone.outerWidth() + oleft;
        var otop = clickZone.offset().top;
        var obottom = clickZone.outerHeight() + otop;

        $("#" + buttonId).mousemove(function (e) {
            var x = e.pageX;
            var y = e.pageY;
            if (!(x < oleft || x > oright || y < otop || y > obottom)) {
                inputFile.offset({
                    top: y - 15,
                    left: x - 160
                });
            } else {
                inputFile.offset({
                    top: -400,
                    left: -400
                });
            }
        });
    }

    document.getElementById(dropZoneId).addEventListener("drop", function (e) {
        $("#" + dropZoneId).removeClass(mouseOverClass);
    }, true);

    inputFile.on('change', function (e) {
        $('#filename').html("");
        var fileNum = this.files.length,
            initial = 0,
            counter = 0,
            fileNames = "";

        for (initial; initial < fileNum; initial++) {
            counter = counter + 1;
            fileNames += this.files[initial].name + '&nbsp;';
        }
        if(fileNum > 1)
            fileNames = 'Files selected...';
        else
            fileNames = this.files[0].name + '&nbsp;';

        $('#filename').append('<span class="fa-stack fa-lg"><i class="fa fa-file fa-stack-1x "></i><strong class="fa-stack-1x" style="color:#FFF; font-size:12px; margin-top:2px;">'+ fileNum + '</strong></span><span">' + fileNames + '</span>&nbsp;<span class="fa fa-times-circle fa-lg closeBtn" title="remove"></span><br>');

        // add remove event
      $('#filename').find('.closeBtn').click(function(){
          $('#filename').empty();
          inputFile.val('');
      });
      ///End change 
    });

})

【讨论】:

  • 实际上您的代码几乎可以工作,但在 UI 中,结果是当您删除 css 部分 ''#drop-zone input'' 时,您将看到队列中的输入文件在按钮中流动,并且当您导入一个或多个文件然后删除它们时,队列中的文件仍然存在,它仍然在后端。
  • 我认为无法在 元素中编辑所选文件的文件数组。这是一种安全风险,因此浏览器不允许这样做。
  • 从这个 JsFiddle 可以看出,您不能在 input.files 上调用 splice。 jsfiddle.net/vpmjqn7u/4这就是我想要做的。脚本到达拼接处时失败。而不是在每个文件名之后显示一个删除图标,如果他们像这个小提琴一样单击名称,您应该只使用重新选择文件。 jsfiddle.net/0GiS0/Yvgc2
  • 我已经阅读了那个封面问题,但我也这样做不是为了我自己的目的而是为了我的客户,请建议其他方式?
  • 我已更新答案以显示总数并在选择多个文件时删除所有选定文件。如果您想从选定的文件中删除单个文件,您应该尝试实施 @KAD 的解决方案。
【解决方案4】:
$(function () {

  var dropZoneId = "drop-zone";
  var buttonId = "clickHere";
  var mouseOverClass = "mouse-over";

  var dropZone = $("#" + dropZoneId);
  var ooleft = dropZone.offset().left;
  var ooright = dropZone.outerWidth() + ooleft;
  var ootop = dropZone.offset().top;
  var oobottom = dropZone.outerHeight() + ootop;
  var inputFile = dropZone.find("input");

  var filesArr = [];

  function showFiles() {
    $('#filename').html("");
    var fileNum = filesArr.length;
    for (var i = 0; i < fileNum; i++) {
      $('#filename').append('<div><span class="fa-stack fa-lg"><i class="fa fa-file fa-stack-1x "></i><strong class="fa-stack-1x" style="color:#FFF; font-size:12px; margin-top:2px;">'+ i + '</strong></span> ' + filesArr[i].name + '&nbsp;&nbsp;<span class="fa fa-times-circle fa-lg closeBtn" title="remove"></span></div>');
      }
  }

  function addFiles(e) {
    var tmp;

    // transfer dropped content to temporary array
    if (e.dataTransfer) {
      tmp = e.dataTransfer.files;
    } else if (e.target) {
      tmp = e.target.files;
    }        

    // Copy the file items into the array 
    for(var i = 0; i < tmp.length; i++) {
      filesArr.push(tmp.item(i));
    }

    // remove all contents from the input elemnent (reset it)
    inputFile.wrap('<form>').closest('form').get(0).reset();
    inputFile.unwrap();

    showFiles();
  }    

  document.getElementById(dropZoneId).addEventListener("dragover", function (e) {
    e.preventDefault();
    e.stopPropagation();
    dropZone.addClass(mouseOverClass);
    var x = e.pageX;
    var y = e.pageY;

    if (!(x < ooleft || x > ooright || y < ootop || y > oobottom)) {
        inputFile.offset({
            top: y - 15,
            left: x - 100
        });
    } else {
        inputFile.offset({
            top: -400,
            left: -400
        });
    }
  }, true);

  if (buttonId != "") {
    var clickZone = $("#" + buttonId);

    var oleft = clickZone.offset().left;
    var oright = clickZone.outerWidth() + oleft;
    var otop = clickZone.offset().top;
    var obottom = clickZone.outerHeight() + otop;

    $("#" + buttonId).mousemove(function (e) {
      var x = e.pageX;
      var y = e.pageY;
      if (!(x < oleft || x > oright || y < otop || y > obottom)) {
          inputFile.offset({
              top: y - 15,
              left: x - 160
          });
      } else {
          inputFile.offset({
              top: -400,
              left: -400
          });
      }
    });
  }
  document.getElementById(dropZoneId).addEventListener("drop", function (e) {
    $("#" + dropZoneId).removeClass(mouseOverClass);
    addFiles(e);
  }, true);

  inputFile.on('change', function(e) {
    addFiles(e);
  });

  $('#filename').on('click', '.closeBtn', function(e) {
    e.preventDefault();
    e.stopPropagation();

    var divElem = $(this).parent();
    var index = $('#filename').find('div').index(divElem);
    if ( index !== -1 ) {
      $('#filename')[0].removeChild(divElem[0]);
      filesArr.slice(index,1);
    }
  });

})

【讨论】:

  • 好的,谢谢,我认为这更好,但会先尝试感谢@code uniquely
  • 你能举个实际的例子吗
  • 无法从此 input.files 数组中删除特定文件。它是只读的。这个问题的答案涵盖了它stackoverflow.com/questions/11173064/…
  • 更新了正在写入范围变量 filesArr 的文件,可用于上传文件(添加文件后重置输入)。从数组呈现并从数组中删除的 HTML 内容。也可以直接使用数组作为任意AJAX请求的数据
【解决方案5】:
$(function () {

  var dropZoneId = "drop-zone";
  var buttonId = "clickHere";
  var mouseOverClass = "mouse-over";

  var dropZone = $("#" + dropZoneId);
  var ooleft = dropZone.offset().left;
  var ooright = dropZone.outerWidth() + ooleft;
  var ootop = dropZone.offset().top;
  var oobottom = dropZone.outerHeight() + ootop;
  var inputFile = dropZone.find("input");

  var filesArr = [];

  function showFiles() {
    $('#filename').html("");
    var fileNum = filesArr.length;
    for (var i = 0; i < fileNum; i++) {

                                objectURL = URL.createObjectURL(filesArr[i]);

      $('#filename').append('<div><img title="'+filesArr[i].name+'" id="'+objectURL+'" src="'+objectURL+'" class="pre-visualizacao"><span class="fa-stack fa-lg"><i class="fa fa-file fa-stack-1x "></i><strong class="fa-stack-1x" style="color:#FFF; font-size:12px; margin-top:2px;">'+ i + '</strong></span> ' + filesArr[i].name + '&nbsp;&nbsp;<span class="closeBtn" title="Remover">X</span></div>');

      }
  }

  function addFiles(e) {
    var tmp;

    // transfer dropped content to temporary array
    if (e.dataTransfer) {
      tmp = e.dataTransfer.files;
    } else if (e.target) {
      tmp = e.target.files;
    }        

    // Copy the file items into the array 
    for(var i = 0; i < tmp.length; i++) {
      filesArr.push(tmp.item(i));
      //console.log(i);
    }

    // remove all contents from the input elemnent (reset it)
    inputFile.wrap('<form>').closest('form').get(0).reset();
    inputFile.unwrap();

    showFiles();
  }    

  document.getElementById(dropZoneId).addEventListener("dragover", function (e) {
    e.preventDefault();
    e.stopPropagation();
    dropZone.addClass(mouseOverClass);
    var x = e.pageX;
    var y = e.pageY;

    if (!(x < ooleft || x > ooright || y < ootop || y > oobottom)) {
        inputFile.offset({
            top: y - 15,
            left: x - 100
        });
    } else {
        inputFile.offset({
            top: -400,
            left: -400
        });
    }
  }, true);

  if (buttonId != "") {
    var clickZone = $("#" + buttonId);

    var oleft = clickZone.offset().left;
    var oright = clickZone.outerWidth() + oleft;
    var otop = clickZone.offset().top;
    var obottom = clickZone.outerHeight() + otop;

    $("#" + buttonId).mousemove(function (e) {
      var x = e.pageX;
      var y = e.pageY;
      if (!(x < oleft || x > oright || y < otop || y > obottom)) {
          inputFile.offset({
              top: y - 15,
              left: x - 160
          });
      } else {
          inputFile.offset({
              top: -400,
              left: -400
          });
      }
    });
  }
  document.getElementById(dropZoneId).addEventListener("drop", function (e) {
    $("#" + dropZoneId).removeClass(mouseOverClass);
    addFiles(e);
  }, true);

  /*inputFile.on('change', function(e) {
    addFiles(e);
  });*/

  $('#filename').on('click', '.closeBtn', function(e) {
    e.preventDefault();
    e.stopPropagation();

    var divElem = $(this).parent();
    var index = $('#filename').find('div').index(divElem);
    if ( index !== -1 ) {
      $('#filename')[0].removeChild(divElem[0]);
      filesArr.slice(index,1);
    }
  });
  inputFile.on('change', function(e) {
    $('#filename').html("");
    var fileNum = this.files.length,
      initial = 0,
      counter = 0;
    for (initial; initial < fileNum; initial++) {
      counter = counter + 1;
      objectURL = URL.createObjectURL(this.files[initial]);
      $('#filename').append('<div><img title="'+this.files[initial].name+'" id="'+objectURL+'" src="'+objectURL+'" class="pre-visualizacao"><span class="fa-stack fa-lg"><i class="fa fa-file fa-stack-1x "></i><strong class="fa-stack-1x" style="color:#FFF; font-size:12px; margin-top:2px;">'+ counter + '</strong></span> ' + this.files[initial].name + '&nbsp;&nbsp;<span class="closeBtn" title="Remover">X</span></div>');
    }
  });

});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    • 1970-01-01
    • 2017-11-07
    相关资源
    最近更新 更多