سؤال

أقوم بإنشاء تطبيق ويب يعمل بالسحب والإفلات للتحميل باستخدام HTML5، ثم أقوم بإسقاط الملفات على div وبالطبع جلب كائن dataTransfer، الذي يمنحني قائمة الملفات.

الآن أريد إزالة بعض الملفات، لكني لا أعرف كيف، أو إذا كان ذلك ممكنًا.

ويفضل أن أقوم بحذفها من قائمة الملفات؛ليس لدي أي فائدة لهم.ولكن إذا لم يكن ذلك ممكنًا، فهل يجب علي بدلاً من ذلك كتابة الشيكات في التعليمات البرمجية التي تتفاعل مع FileList؟يبدو ذلك مرهقًا.

هل كانت مفيدة؟

المحلول

إذا كنت ترغب في حذف العديد من الملفات المحددة فقط: لا يمكنك ذلك. ال ملف واجهة برمجة تطبيقات الملفات كنت مرتبطًا بملاحظة:

ال HTMLInputElement الواجهة [HTML5] لديها ملف يقرأ فقط FileListينسب، […
التأكيد لي

عند قراءة القليل من مسودة العمل HTML 5 ، صادفت مشترك input APIs العنصر. يبدو أنه يمكنك حذف بأكمله قائمة الملفات عن طريق تعيين value خاصية input اعترض على سلسلة فارغة ، مثل:

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

راجع للشغل ، المقال استخدام الملفات من تطبيقات الويب قد يكون أيضا موضع اهتمام.

نصائح أخرى

تم بالفعل وضع علامة "إجابة" على هذا السؤال، ولكني أرغب في مشاركة بعض المعلومات التي قد تساعد الآخرين في استخدام FileList.

سيكون من المناسب التعامل مع FileList كمصفوفة، لكن الأساليب مثل الفرز والتحويل والبوب ​​والتقطيع لا تعمل.كما اقترح الآخرون، يمكنك نسخ FileList إلى مصفوفة.ومع ذلك، بدلاً من استخدام حلقة، هناك حل بسيط من سطر واحد للتعامل مع هذا التحويل.

 // 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;
 });

تم اختباره بشكل جيد في FF، وChrome، وIE10+

إذا كنت تستهدف متصفحات دائمة الخضرة (Chrome ، Firefox ، Edge ، ولكنها تعمل أيضًا في Safari 9+) أو يمكنك تحمل تكاليف Polyfill Array.from() مثله:

let fileArray = Array.from(fileList);

ثم من السهل التعامل مع مجموعة من FileS مثل أي صفيف آخر.

نظرًا لأننا في عالم HTML5 ، هذا هو الحل. GIST هو أنك تدفع الملفات إلى صفيف بدلاً من تركها في أحد الأطراف ، ثم باستخدام XHR2 ، يمكنك دفع الملفات إلى كائن FormData. مثال أدناه.

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."));

لقد وجدت حلًا سريعًا وقصيرًا سريعًا لهذا الغرض. تم اختباره في العديد من المتصفحات الشعبية (Chrome ، Firefox ، Safari) ؛

أولاً ، عليك تحويل Filelist إلى صفيف

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

لحذف العنصر المعين استخدام هذا

newFileList.splice(index,1);

أعلم أن هذا سؤال قديم لكنه يحتل المرتبة العالية في محركات البحث فيما يتعلق بهذه القضية.

الخصائص في الفيللي لا يمكن حذف الكائن ولكن على الأقل على Firefox يمكن تغييرها. كانت هذه المسألة الحل هي إضافة خاصية IsValid=true إلى تلك الملفات التي مررت بالتحقق و IsValid=false لأولئك الذين لم يفعلوا.

ثم أنا فقط أحلق من خلال القائمة للتأكد من أن الخصائص فقط IsValid=true تضاف إلى بيانات النموذج.

قد تكون هناك طريقة أكثر أناقة للقيام بذلك ولكن هنا هو الحل. مع jQuery

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

في الأساس يمكنك ربط قيمة الإدخال. استنساخه ووضع استنساخ بدلاً من القديم.

هذا أمر مؤقت ، لكن كان لدي نفس المشكلة التي حللتها بهذه الطريقة. في حالتي ، كنت أقوم بتحميل الملفات عبر طلب XMLHTTP ، لذلك تمكنت من نشر البيانات المستنسخة من خلال إلحاق FormData. الوظيفة هي أنه يمكنك سحب وإسقاط أو تحديد ملفات متعددة عدة مرات كما تريد (تحديد الملفات مرة أخرى لن يعيد تعيين Filelist المستنسخة) ، وإزالة أي ملف تريده من قائمة الملف تركت هناك. وهذا هو ما فعلته. إنه أول مشاركة لي هنا ، لذا فإن الكود فوضوي قليلاً. آسف. آه ، واضطررت إلى استخدام jQuery بدلاً من $ كما كان في Script Joomla.

// some global variables
var clon = {};  // will be my FileList clone
var removedkeys = 0; // removed keys counter for later processing the request
var NextId = 0; // counter to add entries to the clone and not replace existing ones

jQuery(document).ready(function(){
    jQuery("#form input").change(function () {

    // making the clone
    var curFiles = this.files;
    // temporary object clone before copying info to the clone
    var temparr = jQuery.extend(true, {}, curFiles);
    // delete unnecessary FileList keys that were cloned
    delete temparr["length"];
    delete temparr["item"];

    if (Object.keys(clon).length === 0){
       jQuery.extend(true, clon, temparr);
    }else{
       var keysArr = Object.keys(clon);
       NextId = Math.max.apply(null, keysArr)+1; // FileList keys are numbers
       if (NextId < curFiles.length){ // a bug I found and had to solve for not replacing my temparr keys...
          NextId = curFiles.length;
       }
       for (var key in temparr) { // I have to rename new entries for not overwriting existing keys in clon
          if (temparr.hasOwnProperty(key)) {
             temparr[NextId] = temparr[key];
             delete temparr[key];
                // meter aca los cambios de id en los html tags con el nuevo NextId
                NextId++;
          }
       } 
       jQuery.extend(true, clon, temparr); // copy new entries to clon
    }

// modifying the html file list display

if (NextId === 0){
    jQuery("#filelist").html("");
    for(var i=0; i<curFiles.length; i++) {
        var f = curFiles[i];
        jQuery("#filelist").append("<p id=\"file"+i+"\" style=\'margin-bottom: 3px!important;\'>" + f.name + "<a style=\"float:right;cursor:pointer;\" onclick=\"BorrarFile("+i+")\">x</a></p>"); // the function BorrarFile will handle file deletion from the clone by file id
    }
}else{
    for(var i=0; i<curFiles.length; i++) {
        var f = curFiles[i];
        jQuery("#filelist").append("<p id=\"file"+(i+NextId-curFiles.length)+"\" style=\'margin-bottom: 3px!important;\'>" + f.name + "<a style=\"float:right;cursor:pointer;\" onclick=\"BorrarFile("+(i+NextId-curFiles.length)+")\">x</a></p>"); // yeap, i+NextId-curFiles.length actually gets it right
    }        
}
// update the total files count wherever you want
jQuery("#form p").text(Object.keys(clon).length + " file(s) selected");
    });
});

function BorrarFile(id){ // handling file deletion from clone
    jQuery("#file"+id).remove(); // remove the html filelist element
    delete clon[id]; // delete the entry
    removedkeys++; // add to removed keys counter
    if (Object.keys(clon).length === 0){
        jQuery("#form p").text(Object.keys(clon).length + " file(s) selected");
        jQuery("#fileToUpload").val(""); // I had to reset the form file input for my form check function before submission. Else it would send even though my clone was empty
    }else{
        jQuery("#form p").text(Object.keys(clon).length + " file(s) selected");
    }
}
// now my form check function

function check(){
    if( document.getElementById("fileToUpload").files.length == 0 ){
        alert("No file selected");
        return false;
    }else{
        var _validFileExtensions = [".pdf", ".PDF"]; // I wanted pdf files
        // retrieve input files
        var arrInputs = clon;

       // validating files
       for (var i = 0; i < Object.keys(arrInputs).length+removedkeys; i++) {
         if (typeof arrInputs[i]!="undefined"){
           var oInput = arrInputs[i];
           if (oInput.type == "application/pdf") {
               var sFileName = oInput.name;
               if (sFileName.length > 0) {
                   var blnValid = false;
                   for (var j = 0; j < _validFileExtensions.length; j++) {
                     var sCurExtension = _validFileExtensions[j];
                     if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).toLowerCase() == sCurExtension.toLowerCase()) {
                       blnValid = true;
                       break;
                     }
                   }
                  if (!blnValid) {
                    alert("Sorry, " + sFileName + " is invalid, allowed extensions are: " + _validFileExtensions.join(", "));
                    return false;
                  }
              }
           }else{
           alert("Sorry, " + arrInputs[0].name + " is invalid, allowed extensions are: " + _validFileExtensions.join(" or "));
           return false;
           }
         }
       }

    // proceed with the data appending and submission
    // here some hidden input values i had previously set. Now retrieving them for submission. My form wasn't actually even a form...
    var fecha = jQuery("#fecha").val();
    var vendor = jQuery("#vendor").val();
    var sku = jQuery("#sku").val();
    // create the formdata object
    var formData = new FormData();
    formData.append("fecha", fecha);
    formData.append("vendor", encodeURI(vendor));
    formData.append("sku", sku);
    // now appending the clone file data (finally!)
    var fila = clon; // i just did this because I had already written the following using the "fila" object, so I copy my clone again
    // the interesting part. As entries in my clone object aren't consecutive numbers I cannot iterate normally, so I came up with the following idea
    for (i = 0; i < Object.keys(fila).length+removedkeys; i++) { 
        if(typeof fila[i]!="undefined"){
            formData.append("fileToUpload[]", fila[i]); // VERY IMPORTANT the formdata key for the files HAS to be an array. It will be later retrieved as $_FILES['fileToUpload']['temp_name'][i]
        }
    }
    jQuery("#submitbtn").fadeOut("slow"); // remove the upload btn so it can't be used again
    jQuery("#drag").html(""); // clearing the output message element
    // start the request
    var xhttp = new XMLHttpRequest();
    xhttp.addEventListener("progress", function(e) {
            var done = e.position || e.loaded, total = e.totalSize || e.total;
        }, false);
        if ( xhttp.upload ) {
            xhttp.upload.onprogress = function(e) {
                var done = e.position || e.loaded, total = e.totalSize || e.total;
                var percent = done / total;
                jQuery("#drag").html(Math.round(percent * 100) + "%");
            };
        }
      xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
         var respuesta = this.responseText;
         jQuery("#drag").html(respuesta);
        }
      };
      xhttp.open("POST", "your_upload_handler.php", true);  
      xhttp.send(formData);
    return true;
    }
};

الآن HTML والأنماط لهذا الغرض. أنا مبتدئ تمامًا ولكن كل هذا كان يعمل بالفعل بالنسبة لي وأخذني بعض الوقت لمعرفة ذلك.

<div id="form" class="formpos">
<!--    Select the pdf to upload:-->
  <input type="file" name="fileToUpload[]" id="fileToUpload" accept="application/pdf" multiple>
  <div><p id="drag">Drop your files here or click to select them</p>
  </div>
  <button id="submitbtn" onclick="return check()" >Upload</button>
// these inputs are passed with different names on the formdata. Be aware of that
// I was echoing this, so that's why I use the single quote for php variables
  <input type="hidden" id="fecha" name="fecha_copy" value="'.$fecha.'" />
  <input type="hidden" id="vendor" name="vendorname" value="'.$vendor.'" />
  <input type="hidden" id="sku" name="sku" value="'.$sku.'"" />
</div>
<h1 style="width: 500px!important;margin:20px auto 0px!important;font-size:24px!important;">File list:</h1>
<div id="filelist" style="width: 500px!important;margin:10px auto 0px!important;">Nothing selected yet</div>

الأنماط لذلك. اضطررت إلى وضع علامة على بعضهم! من المهم تجاوز سلوك جملة.

.formpos{
  width: 500px;
  height: 200px;
  border: 4px dashed #999;
  margin: 30px auto 100px;
 }
.formpos  p{
  text-align: center!important;
  padding: 80px 30px 0px;
  color: #000;
}
.formpos  div{
  width: 100%!important;
  height: 100%!important;
  text-align: center!important;
  margin-bottom: 30px!important;
}
.formpos input{
  position: absolute!important;
  margin: 0!important;
  padding: 0!important;
  width: 500px!important;
  height: 200px!important;
  outline: none!important;
  opacity: 0!important;
}
.formpos button{
  margin: 0;
  color: #fff;
  background: #16a085;
  border: none;
  width: 508px;
  height: 35px;
  margin-left: -4px;
  border-radius: 4px;
  transition: all .2s ease;
  outline: none;
}
.formpos button:hover{
  background: #149174;
  color: #0C5645;
}
.formpos button:active{
  border:0;
}

آمل أن يساعد هذا.

إذا كان لديك حظ لإرسال طلب نشر إلى قاعدة البيانات مع الملفات ولديك الملفات التي تريد إرسالها في دوم الخاص بك

يمكنك ببساطة التحقق مما إذا كان الملف الموجود في قائمة الملفات موجودًا في DOM الخاص بك ، وبالطبع إذا لم يكن الأمر كذلك ، فأنت لا ترسل هذا العنصر إلى DE DB.

شكرًا @nicholas Anderson بسيط ومستقيم ، إليك الكود الخاص بك المطبق والعمل على الكود الخاص بي باستخدام jQuery.

لغة البرمجة .

<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

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

قد ترغب في إنشاء صفيف واستخدام ذلك بدلاً من القراءة فقط.

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

بعد هذه النقطة ، قم بتحميلك مقابل قائمتك بدلاً من القائمة المدمجة. لست متأكدًا من السياق الذي تعمل فيه ، لكنني أعمل مع مكون مكون الإضافي الذي وجدته وما كان علي فعله هو أخذ مصدر البرنامج المساعد ووضعه في الصفحة باستخدام <script> العلامات. ثم فوق المصدر ، أضفت صفيف بلدي حتى يمكن أن يكون بمثابة متغير عالمي ويمكن للمكون الإضافي الرجوع إليه.

ثم كانت مجرد مسألة تبديل المراجع.

أعتقد أن هذا سيسمح لك أيضًا بإضافة Drag & Drop مرة أخرى ، إذا كانت القائمة المضمنة للقراءة فقط ، فكيف يمكنك إدخال الملفات المسقطة في القائمة؟

:))

أنا فقط أغير نوع الإدخال إلى النص والعودة إلى الملف: د

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top