简体   繁体   中英

Multiple file upload - check which of the files exist on server by Ajax-request

I can't seem to find what's wrong with the idea of this script and can't get it to work. Maybe you can help me, it would be highly appreciated.

I'm working on a multiple file upload form. Prior to uploading (and not before then) I want to check whether some of the files (and if so, which ones) already exist in the upload directory. I'm using XMLHttpRequests to do that. Since I can't control how long exactly those will take to get a response I run a loop using arrays for all the variables so they (at least that was my idea ;-) ) can do their job indepently from each other.

function NoOverwrite() {
var fields = document.querySelectorAll("input[type=file]");
var existing = new Array(); //files existing on server
var checkFile = new Array();
var file = new Array();
var fileUrl = new Array();
for (var i = 0; i < fields.length; i++) {
    file[i] = document.getElementById('file'+i).files[0];  
    //the input- fields of the form are called file0, file1, file2, and so on...
    if(file[i]) {
        fileUrl[i] = 'upload_path/' + file[i].name; 
        //up to here everything works fine - when setting an alert after this I get 
        //the names of all the names of the files selected in the file fields! 
        checkFile[i] = new XMLHttpRequest();
        checkFile[i].open('HEAD', fileUrl[i], true);
        checkFile[i].onreadystatechange = function() {
            if (checkFile[i].readyState == 4) {
                if (checkFile[i].status == 200) {
                    existing[i] = true; 
                    alert(existing[i]);     //this never came up... 
                }
            }
        checkFile[i].send();
        }
    }
}
if (existing.indexOf(true) == -1) {
    //none of the files to be uploaded are already on server
    //this _always_ was fired - even when there are files with the same name on the server!!!??
    return true; 
}
else {
    //list filenames and/or upload field numbers of the files that already exist on server
    return false;
   }
}

Did I make an error in my thinking? Or are there some simple mistakes in my code? Any ideas how I could archive my goal?

I see two potential issues with your code.

The first one is the same origin policy : if upload_path is not in the same domain as your current page, the request might fail.

The second is your index: as i increases, when you do alert(existing[i]) i is already equal to fields.length. You need to create a closure:

for (var i = 0; i < fields.length; i++) {
    (function(index){
    // use index within your code
    })(i); // the loop will execute with index=i
}

Ok, I found the answer - just in case anyone is interested...

In addition to Christophes remark that a closure for the loop has to be created, the checking of the array of course also has to happen inside that loop function, otherwise it's checked immediately (ie when there hasn't been a single response of the XMLHttpRequests yet) and since it is only checked once, it will always be negative. Apart from that we have to make sure that ALL requests are finished (not just being processed) before we check the values in the array. We do that by comparing the number of filled in upload fields against the number of values that have been set into the string (which happens after the readystate-response of the corresponding request came back). More explanations in the code.

Cheers, Chris

function NoOverwrite() {
var fields = document.querySelectorAll("input[type=file]");
var existing = new Array();
var checkFile = new Array();
var file = new Array();
var fileUrl = new Array();
var counter = 0;
for (var i = 0; i < fields.length; i++) {
    (function(index){
        file[index] = document.getElementById('file'+i).files[0];
        if(file[index]) {
            fileUrl[index] = 'upload_path/' + file[index].name;
            checkFile[index] = new XMLHttpRequest();
            checkFile[index].onreadystatechange = function() {
                if (checkFile[index].readyState == 4) {
                    if (checkFile[index].status == 200) {
                        existing[index] = true; 
                        counter += 1;
                    }
                    else {
                        existing[index] = false;
                        counter += 1;
                    }
                    if (counter == fileUrl.length) { 
                            //existing.length of the array "true, false,,true" (i.e. with one undefined value) would deliver "4". 
                            //therefore we have to check for the number of set variables in the string rather than the strings length. 
                            //we use a counter for that purpose. everything after this point is only executed when the last file has been checked! 
                        if (existing.indexOf(true) == -1) {
                            //none of the files to be uploaded are already on server
                            return true; 
                        }
                        else {
                            //list filenames and/or upload field numbers of the files that already exist on server
                            //   ->> inform user... 
                            return false;
                        }
                    }
                }
            }
            checkFile[index].open('HEAD', fileUrl[index], true);
            checkFile[index].send();
        }
    })(i);
}
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM