Удаление файла из загрузчика нескольких файлов при нажатии кнопки при использовании ввода файла HTML5

Как добавить сюда кнопку удалить, например, просто удалить один за другим в очереди файлов, как это

введите здесь описание изображения

Причина, по которой я не использую бесплатные плагины для загрузки файлов с плагинами OOB, потому что требования моего клиента связаны с безопасностью, и им нужен простой интерфейс загрузки без каких-либо сложных плагинов.

$(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


person 光 Hikari No kun    schedule 18.08.2015    source источник
comment
См. stackoverflow.com/q/29841147 , stackoverflow.com/q/32002431   -  person guest271314    schedule 22.08.2015
comment
Дублирование stackoverflow.com/questions/3144419/   -  person Medet Tleukabiluly    schedule 23.08.2015
comment
о, извините, плохо, я не заметил их, прежде чем спросил, я сначала ищу, но еще раз спасибо, ребята, что упомянули об этом.   -  person 光 Hikari No kun    schedule 23.08.2015


Ответы (4)


Список файлов ввода файлов HTML5 доступен только для чтения, поэтому при попытке удалить файл из него вы не будете допущены.

Что вам нужно сделать, так это сохранить отдельный список массивов (массив JSON, как в примере).

Я обернул вашу кнопку X элементом div, который содержит индекс файла, связанный со строкой «file_», и добавил функцию onclick removeLine(obj), которая принимает элемент как объект.

Я также добавил массив JSON finalFiles в глобальную область, а также переместил inputFile в глобальную область.

Когда ввод файла изменяется, я устанавливаю массив JSON с выбранными файлами через:

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

Функция removeLine очистит список входных файлов, чтобы снова разрешить тот же выбор файла, если пользователь удалил файл по ошибке, функция получает индекс файла из идентификатора подразделения оболочки, удаляет 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);
    }

Вы можете сохранить свои файлы при отправке формы и отправить их через публикацию AJAX, используя FormData аналогично этой статье.

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>

person KAD    schedule 21.08.2015
comment
Спасибо @KAD, я попробую это. - person 光 Hikari No kun; 21.08.2015
comment
вы работаете почти идеально, одна вещь может улучшить это, когда вы импортируете несколько файлов, а затем удаляете один файл из группы, который является только тем файлом, который является вашей целью, все файлы в элементе также удаляются, вы можете увидеть элемент файла, если вы удалите часть css #drop-zone input кстати еще раз спасибо. - person 光 Hikari No kun; 21.08.2015
comment
Как я могу отправить его? - person Thiago; 11.06.2016
comment
Вы используете formdata при отправке файлов? - person KAD; 18.11.2016
comment
Привет. У меня есть один вопрос. Когда я удаляю один файл из списка, нажав значок закрытия, форма отправит те файлы, которые остались в списке? - person X9DESIGN; 28.05.2017
comment
FormData является родным - person Donato; 21.06.2017

Я делал это раньше для своей 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));
person Matt Komarnicki    schedule 21.08.2015
comment
Хорошо, я попробую это Спасибо @slick - person 光 Hikari No kun; 21.08.2015

Поскольку мы не можем изменить массив выбранных файлов в теге <input type'file' multiple>, я обновил ваш код, чтобы показать количество файлов и удалить все файлы, если выбрано несколько файлов.

Есть фрагмент обновленного кода.

$(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 
    });

})
person Padhraic    schedule 21.08.2015
comment
На самом деле ваш код почти работает, но в пользовательском интерфейсе результат заключается в том, что когда вы удаляете часть css ''#drop-zone input'', вы увидите, что входной файл в очереди перемещается по кнопке, и когда вы импортируете один или несколько файлов, затем удалите их, файл в очереди останется, который находится в бэкэнде, он все еще их. - person 光 Hikari No kun; 21.08.2015
comment
Я не думаю, что возможно редактировать массив файлов выбранных файлов в вашем элементе ‹input type='file' Multiple›. Это угроза безопасности, поэтому браузеры этого не позволяют. - person Padhraic; 21.08.2015
comment
Как вы можете видеть из этого JsFiddle, вы не можете вызывать splice для input.files. jsfiddle.net/vpmjqn7u/4 Это то, что я пытался сделать. Сценарий завершается сбоем, когда он достигает соединения. Вместо того, чтобы показывать значок удаления после каждого имени файла, вы должны просто повторно выбрать файлы, если они щелкнут имя, подобное этой скрипке. jsfiddle.net/0GiS0/Yvgc2 - person Padhraic; 21.08.2015
comment
Я уже прочитал этот вопрос, но я также делаю это не для себя, а для моего клиента, пожалуйста, предложите другой способ? - person 光 Hikari No kun; 21.08.2015
comment
Я обновил ответ, чтобы показать общее количество и удалить все выбранные файлы, когда выбрано несколько файлов. Если вы хотите удалить отдельные файлы из выбранных, попробуйте реализовать решение @KAD. - person Padhraic; 21.08.2015
comment
хахаха, это идея получше, я буду использовать ее для других целей, но на данный момент я рассчитываю на решение @KAD - person 光 Hikari No kun; 21.08.2015
comment
Спасибо, приятель, за это, я использую его прямо сейчас, я объединяю вашу работу и решение @KAD и даю мне именно то, что я ищу ... - person 光 Hikari No kun; 25.08.2015

person    schedule
comment
Хорошо, спасибо, я думаю, что это лучше, но сначала попробую, спасибо @code уникально - person 光 Hikari No kun; 21.08.2015
comment
можешь привести реальный пример - person 光 Hikari No kun; 21.08.2015
comment
Невозможно удалить определенный файл из этого массива input.files. Это только для чтения. Ответ на этот вопрос охватывает его stackoverflow.com/questions/11173064/ - person Padhraic; 21.08.2015
comment
Обновлено: файлы записываются в переменную с областью действия filesArr, которую можно использовать для загрузки файлов (ввод сбрасывается после добавления файлов). Содержимое HTML отображается из массива и удаляется из массива. Вы также можете использовать массив напрямую как данные любого запроса AJAX. - person Code Uniquely; 21.08.2015