Hoe verwijder ik een bestand uit de FileList

Ik bouw een webtoepassing met slepen en neerzetten om te uploaden met HTML5, en ik zet de bestanden neer op een div en natuurlijk haal ik het dataTransfer-object op, wat me de FileList.

Nu wil ik enkele bestanden verwijderen, maar ik weet niet hoe, en of het zelfs mogelijk is.

Het liefst zou ik ze gewoon uit de FileList willen verwijderen; Ik heb niets aan ze. Maar als dat niet mogelijk is, moet ik dan in plaats daarvan checks-in-code schrijven die interageert met de FileList? Dat lijkt omslachtig.


Antwoord 1, autoriteit 100%

Als u slechts enkele van de geselecteerde bestanden wilt verwijderen: dat kan niet. De File API Working Draftwaarnaar u hebt gelinkt, bevat een opmerking:

De HTMLInputElement-interface
[HTML5] heeft een alleen-lezenFileList
attribuut, […]
[nadruk van mij]

Bij het lezen van een stukje HTML 5 Working Draft, kwam ik de Gemeenschappelijke inputelement-API’s. Het lijkt erop dat u de volledigebestandslijst kunt verwijderen door de eigenschap valuevan het input-object in te stellen op een lege tekenreeks, zoals:

document.getElementById('multifile').value = "";

BTW, het artikel Bestanden uit webapplicaties gebruikenkan ook interessant zijn.


Antwoord 2, autoriteit 18%

Deze vraag is al als beantwoord gemarkeerd, maar ik wil graag wat informatie delen die anderen kan helpen bij het gebruik van FileList.

Het zou handig zijn om een ​​FileList als een array te behandelen, maar methoden als sorteren, shift, pop en slice werken niet. Zoals anderen hebben gesuggereerd, kunt u de FileList naar een array kopiëren. In plaats van een lus te gebruiken, is er echter een eenvoudige éénregelige oplossing om deze conversie af te handelen.

// fileDialog.files is a FileList 
 var fileBuffer=[];
 // append the file list to an array
 Array.prototype.push.apply( fileBuffer, fileDialog.files ); // <-- here
 // And now you may manipulated the result as required
 // shift an item off the array
 var file = fileBuffer.shift(0,1);  // <-- works as expected
 console.info( file.name + ", " + file.size + ", " + file.type );
 // sort files by size
 fileBuffer.sort(function(a,b) {
    return a.size > b.size ? 1 : a.size < b.size ? -1 : 0;
 });

OK getest in FF, Chrome en IE10+


Antwoord 3, autoriteit 14%

Als u zich richt op groenblijvende browsers (Chrome, Firefox, Edge, maar werkt ook in Safari 9+) of als u zich een polyfill kunt veroorloven, kunt u de FileList in een array veranderen door Array.from()zoals dit:

let fileArray = Array.from(fileList);

Dan is het gemakkelijk om de array van File‘s te verwerken zoals elke andere array.


Antwoord 4, autoriteit 11%

Aangezien JavaScript FileList alleen-lezen is en niet rechtstreeks kan worden gemanipuleerd,

BESTE METHODE

Je moet door de input.filesbladeren terwijl je het vergelijkt met de indexvan het bestand dat je wilt verwijderen. Tegelijkertijd gebruikt u new DataTransfer()om een ​​nieuwe lijst met bestanden in te stellen, met uitzondering van het bestand dat u uit de bestandenlijst wilt verwijderen.

Met deze aanpak wordt de waarde van de input.fileszelf gewijzigd.

removeFileFromFileList(index) {
  const dt = new DataTransfer()
  const input = document.getElementById('files')
  const { files } = input
  for (let i = 0; i < files.length; i++) {
    const file = files[i]
    if (index !== i)
      dt.items.add(file) // here you exclude the file. thus removing it.
  }
  input.files = dt.files // Assign the updates list
}

ALTERNATIEVE METHODE

Een andere eenvoudige methode is om de FileList naar een array te converteren en deze vervolgens te splitsen.

Maar deze aanpak verandert niets aan de input.files

const input = document.getElementById('files')
// as an array, u have more freedom to transform the file list using array functions.
const fileListArr = Array.from(input.files)
fileListArr.splice(index, 1) // here u remove the file
console.log(fileListArr)

Antwoord 5, autoriteit 8%

Aangezien we ons in het HTML5-rijk bevinden, is dit mijn oplossing. De essentie is dat u de bestanden naar een array pusht in plaats van ze in een FileList achter te laten, en vervolgens XHR2 gebruikt, u pusht de bestanden naar een FormData-object. Voorbeeld hieronder.

Node.prototype.replaceWith = function(node)
{
    this.parentNode.replaceChild(node, this);
};
if(window.File && window.FileList)
{
    var topicForm = document.getElementById("yourForm");
    topicForm.fileZone = document.getElementById("fileDropZoneElement");
    topicForm.fileZone.files = new Array();
    topicForm.fileZone.inputWindow = document.createElement("input");
    topicForm.fileZone.inputWindow.setAttribute("type", "file");
    topicForm.fileZone.inputWindow.setAttribute("multiple", "multiple");
    topicForm.onsubmit = function(event)
    {
        var request = new XMLHttpRequest();
        if(request.upload)
        {
            event.preventDefault();
            topicForm.ajax.value = "true";
            request.upload.onprogress = function(event)
            {
                var progress = event.loaded.toString() + " bytes transfered.";
                if(event.lengthComputable)
                progress = Math.round(event.loaded / event.total * 100).toString() + "%";
                topicForm.fileZone.innerHTML = progress.toString();
            };
            request.onload = function(event)
            {
                response = JSON.parse(request.responseText);
                // Handle the response here.
            };
            request.open(topicForm.method, topicForm.getAttribute("action"), true);
            var data = new FormData(topicForm);
            for(var i = 0, file; file = topicForm.fileZone.files[i]; i++)
                data.append("file" + i.toString(), file);
            request.send(data);
        }
    };
    topicForm.fileZone.firstChild.replaceWith(document.createTextNode("Drop files or click here."));
    var handleFiles = function(files)
    {
        for(var i = 0, file; file = files[i]; i++)
            topicForm.fileZone.files.push(file);
    };
    topicForm.fileZone.ondrop = function(event)
    {
        event.stopPropagation();
        event.preventDefault();
        handleFiles(event.dataTransfer.files);
    };
    topicForm.fileZone.inputWindow.onchange = function(event)
    {
        handleFiles(topicForm.fileZone.inputWindow.files);
    };
    topicForm.fileZone.ondragover = function(event)
    {
        event.stopPropagation();
        event.preventDefault();
    };
    topicForm.fileZone.onclick = function()
    {
        topicForm.fileZone.inputWindow.focus();
        topicForm.fileZone.inputWindow.click();
    };
}
else
    topicForm.fileZone.firstChild.replaceWith(document.createTextNode("It's time to update your browser."));

Antwoord 6, autoriteit 5%

Ik heb heel snel gevonden & korte oplossing hiervoor. Getest in veel populaire browsers (Chrome, Firefox, Safari);

Eerst moet u FileList naar een array converteren

var newFileList = Array.from(event.target.files);

gebruik dit om het specifieke element te verwijderen

newFileList.splice(index,1);

Antwoord 7, autoriteit 3%

Ik weet dat dit een oude vraag is, maar deze staat hoog in de zoekmachines met betrekking tot dit probleem.

eigenschappen in het FileList-object kunnen niet worden verwijderd, maar in Firefox kunnen ze tenminste worden gewijzigd. Mijn tijdelijke oplossing voor dit probleem was om een ​​eigenschap IsValid=truetoe te voegen aan de bestanden die de controle hebben doorstaan ​​en IsValid=falseaan de bestanden die dat niet deden.

vervolgens loop ik gewoon door de lijst om ervoor te zorgen dat alleen de eigenschappen met IsValid=trueworden toegevoegd aan FormData.


Antwoord 8

Bedankt @Nicholas Anderson, eenvoudig en duidelijk, hier is je code toegepast en werkt aan mijn code met behulp van jQuery.

HTML .

<input class="rangelog btn border-aero" id="file_fr" name="file_fr[]" multiple type="file" placeholder="{$labels_helpfiles_placeholder_file}">
<span style="cursor: pointer; cursor: hand;" onclick="cleanInputs($('#file_fr'))"><i class="fa fa-trash"></i> Empty chosen files</span>

JS-CODE

  function cleanInputs(fileEle){
    $(fileEle).val("");
    var parEle = $(fileEle).parent();
    var newEle = $(fileEle).clone()
    $(fileEle).remove();
    $(parEle).prepend(newEle);
}

Antwoord 9

Er is misschien een elegantere manier om dit te doen, maar hier is mijn oplossing. Met JQuery

fileEle.value = "";
var parEle = $(fileEle).parent();
var newEle = $(fileEle).clone()
$(fileEle).remove();
parEle.append(newEle);

In principe cleat je de waarde van de invoer. Kloon het en plaats de kloon in plaats van de oude.


Antwoord 10

Als je het geluk hebt om een ​​postverzoek naar de database te sturen met de bestanden en je hebt de bestanden die je wilt verzenden in je DOM

je kunt gewoon controleren of het bestand in de bestandenlijst aanwezig is in je DOM, en natuurlijk, als dat niet het geval is, stuur je dat element gewoon niet naar de DB.


Antwoord 11

Ik realiseer me dat dit een vrij oude vraag is, maar ik gebruik een html-upload van meerdere bestanden om een ​​willekeurig aantal bestanden in de wachtrij te plaatsen die selectief kunnen worden verwijderd in een aangepaste gebruikersinterface voordat ze worden verzonden.

Bestanden opslaan in een variabele zoals deze:

let uploadedFiles = [];
//inside DOM file select "onChange" event
let selected = e.target.files[0] ? e.target.files : [];
uploadedFiles = [...uploadedFiles , ...selected ];
createElements();

Maak een gebruikersinterface met “verwijder een bestand”:

function createElements(){
  uploadedFiles.forEach((f,i) => {
    //remove DOM elements and re-create them here
    /* //you can show an image like this:
    *  let reader = new FileReader();
    *  reader.onload = function (e) {
    *    let url = e.target.result;
    *    // create <img src=url />
    *  };
    *  reader.readAsDataURL(f);
    */
    element.addEventListener("click", function () {
      uploadedFiles.splice(i, 1);
      createElements();
    });
  }
}

Verzenden naar server:

let fd = new FormData();
uploadedFiles.forEach((f, i) => {
  fd.append("files[]", f);
});
fetch("yourEndpoint", { 
  method: "POST", 
  body: fd, 
  headers: { 
    //do not set Content-Type 
  } 
}).then(...)

Antwoord 12

Ik mix de oplossingen van veel ontwikkelaars en bereik deze oplossing.
Het verandert de originele arraylijst na verwijdering, wat betekent dat als we de afbeeldingen willen opslaan, we dat kunnen doen.

<script>
    var images = [];
      function image_select() {
          var image = document.getElementById('image').files;
          for (i = 0; i < image.length; i++) {
            images.push({
                "name" : image[i].name,
                "url" : URL.createObjectURL(image[i]),
                "file" : image[i],
            })
          }
          document.getElementById('container').innerHTML = image_show();
      }
      function image_show() {
          var image = "";
          images.forEach((i) => {
             image += `<div class="image_container d-flex justify-content-center position-relative">
                  <img src="`+ i.url +`" alt="Image">
                  <span class="position-absolute" onclick="delete_image(`+ images.indexOf(i) +`)">&times;</span>
              </div>`;
          })
          return image;
      }
      function delete_image(e) {
        images.splice(e, 1);
        document.getElementById('container').innerHTML = image_show();
        const dt = new DataTransfer()
        const input = document.getElementById('image')
        const { files } = input
        for (let i = 0; i < files.length; i++) {
            const file = files[i]
            if (e !== i)
            dt.items.add(file);
        }
        input.files = dt.files;
        console.log(document.getElementById('image').files);
      }
</script>

*******Dit is html-code ******

<body>
    <div class="container mt-3 w-100">
        <div class="card shadow-sm w-100">
            <div class="card-header d-flex justify-content-between">
                <h4>Preview Multiple Images</h4>
                <form class="form" action="{{route('store')}}" method="post" id="form" enctype="multipart/form-data">
                    @csrf
                    <input type="file" name="image[]" id="image" multiple onchange="image_select()">
                    <button class="btn btn-sm btn-primary" type="submit">Submit</button>
                </form>
            </div>
            <div class="card-body d-flex flex-wrap justify-content-start" id="container">
            </div>
        </div>
    </div>
</body>

******* Dit is CSS-code ******

<style>
        .image_container {
    height: 120px;
    width: 200px;
    border-radius: 6px;
    overflow: hidden;
    margin: 10px;
}
.image_container img {
    height: 100%;
    width: auto;
    object-fit: cover;
}
.image_container span {
    top: -6px;
    right: 8px;
    color: red;
    font-size: 28px;
    font-weight: normal;
    cursor: pointer;
}
    </style>

Antwoord 13

Misschien wil je een array maken en die gebruiken in plaats van de alleen-lezen bestandslijst.

var myReadWriteList = new Array();
// user selects files later...
// then as soon as convenient... 
myReadWriteList = FileListReadOnly;

Vervolgens uploadt u tegen uw lijst in plaats van tegen de ingebouwde lijst. Ik ben niet zeker van de context waarin u werkt, maar ik werk met een jQuery-plug-in die ik heb gevonden en wat ik moest doen was de bron van de plug-in nemen en deze op de pagina plaatsen met behulp van <script>labels. Vervolgens heb ik boven de bron mijn array toegevoegd zodat het kan fungeren als een globale variabele en de plug-in ernaar kan verwijzen.

Toen was het een kwestie van de referenties omwisselen.

Ik denk dat je hiermee ook drag & drop as again, als de ingebouwde lijst alleen-lezen is, hoe kun je dan anders de gedropte bestanden in de lijst krijgen?

:))


Antwoord 14

Ik los het op deze manier op

//position  -> the position of the file you need to delete
  this.fileImgs.forEach((item, index, object) => {
     if(item.idColor === idC){
        if(item.imgs.length === 1){
            object.splice(index,1) }
        else{
           const itemFileImgs = [...item.imgs];
           itemFileImgs.splice(position,1)
           item.imgs = [...itemFileImgs] 
            }
        }});
      console.log(this.fileImgs)

voer hier de afbeeldingsbeschrijving in


Antwoord 15

In vue js :

self.$refs.inputFile.value = ''

Snippet uitvouwen


Antwoord 16

Ik verander gewoon het type invoer naar de tekst en terug naar het bestand 😀

Other episodes