Hello guys,
i'll try to explain the problem i am facing here. I had searched for many file uploaders with drag and drop interface. I came across something at http://demos.9lessons.info/multiupload/index.php called the multiuploader. I saw the code and it was a bit of nightmare to me as am not so great at jquery and PHP is what i am good at. I am developing an App using Codeigniter and media uploader is an essential part of the app. I am aiming to create a file uploader like WordPress Media Uploader. Now its going is really really difficult to integrate the file uploader with CI through AJAX so just for now i thought of creating the upload.php in a folder called AJAX which i places at the root of the CI files i.e outside the applications/ folder.

Thats the brief landscape of the platform i am working on right now. If you use the above link the files after uploading shows up on the drag and drop area with an onclick event on the blue upload button to upload all the files. i successfully modified the entire layout. Instead of an on click, i made it to upload the files automatically on drag and drop itself and decorated a little bit.

This is the original code in the multiuploader.js

function multiUploader(config){
    this.config = config;
    this.items = "";
    this.all = []
    var self = this;
    var uploadBtn = $('#uploadbtn'),
        defaultUploadBtn = $('#multiUpload');
    uploadBtn.on('click', function(e) {
        e.stopPropagation();
        e.preventDefault();
        //trigger default file upload button
        defaultUploadBtn.click();
    });
    multiUploader.prototype._init = function(){
        if (window.File && 
            window.FileReader && 
            window.FileList && 
            window.Blob) {      
             var inputId = $("#"+this.config.form).find("input[type='file']").eq(0).attr("id");
             document.getElementById(inputId).addEventListener("change", this._read, false);
             document.getElementById(this.config.dragArea).addEventListener("dragover", function(e){ e.stopPropagation(); e.preventDefault(); }, false);
             document.getElementById(this.config.dragArea).addEventListener("drop", this._dropFiles, false);
             document.getElementById(this.config.dragArea).addEventListener("drop", this._submit, false);
             document.getElementById(this.config.form).addEventListener("change", this._submit, false);
        } else
            console.log("Browser supports failed");
    }
    multiUploader.prototype._submit = function(e){
        e.stopPropagation(); e.preventDefault();
        self._startUpload();
    }
    multiUploader.prototype._preview = function(data){
        this.items = data;
        if(this.items.length > 0){
            var html = "";      
            var uId = "";
            for(var i = 0; i<this.items.length; i++){
                uId = this.items[i].name._unique();
                var sampleIcon = '<img src="images/image.png" />';
                var errorClass = "";
                if(typeof this.items[i] != undefined){
                    if(self._validate(this.items[i].type) <= 0) {
                        sampleIcon = '<img src="images/unknown.png" />';
                        errorClass =" invalid";
                    } 
                    html += '<div class="dfiles'+errorClass+'" rel="'+uId+'"><h5>'+sampleIcon+this.items[i].name+'</h5><div id="'+uId+'" class="progress" style="display:none; font-size: 11px">Edit Media</div></div>';
                }
            }
            $("#filelist").append(html);
        }
    }
    multiUploader.prototype._read = function(evt){
        if(evt.target.files){
            self._preview(evt.target.files);
            self.all.push(evt.target.files);
        } else 
            console.log("Failed file reading");
    }
    multiUploader.prototype._validate = function(format){
        var arr = this.config.support.split(",");
        return arr.indexOf(format);
    }
    multiUploader.prototype._dropFiles = function(e){
        e.stopPropagation(); e.preventDefault();
        self._preview(e.dataTransfer.files);
        self.all.push(e.dataTransfer.files);
    }
    multiUploader.prototype._uploader = function(file,f){
        if(typeof file[f] != undefined && self._validate(file[f].type) > 0){
            var data = new FormData();
            var ids = file[f].name._unique();
            data.append('file',file[f]);
            data.append('index',ids);
            $(".dfiles[rel='"+ids+"']").find(".progress").show();
            $.ajax({
                type:"POST",
                url:this.config.uploadUrl,
                data:data,
                cache: false,
                contentType: false,
                processData: false,
                success:function(rponse){
                    $("#"+ids).hide();
                    var obj = $(".dfiles").get();
                    $.each(obj,function(k,fle){
                        if($(fle).attr("rel") == rponse){
//                          alert(rponse);
                    //      $(fle).slideUp("normal", function(){ $(this).remove(); });
                        }
                    });
                    if (f+1 < file.length) {
                        self._uploader(file,f+1);
                    }
                }
            });
        } else
            console.log("Invalid file format - "+file[f].name);
    }
    multiUploader.prototype._startUpload = function(){
        if(this.all.length > 0){
            for(var k=0; k<this.all.length; k++){
                var file = this.all[k];
                this._uploader(file,0);
            }
        }
    }
    String.prototype._unique = function(){
        return this.replace(/[a-zA-Z]/g, function(c){
           return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
        });
    }
    this._init();
}
function initMultiUploader(){
    new multiUploader(config);
}

I changed some few lines in it and below given is the modified multiuploader.js file

function multiUploader(config){
    this.config = config;
    this.items = "";
    this.all = []
    var self = this;
    var uploadBtn = $('#uploadbtn'),
        defaultUploadBtn = $('#multiUpload');
    uploadBtn.on('click', function(e) {
        e.stopPropagation();
        e.preventDefault();
        //trigger default file upload button
        defaultUploadBtn.click();
    });
    multiUploader.prototype._init = function(){
        if (window.File && 
            window.FileReader && 
            window.FileList && 
            window.Blob) {      
             var inputId = $("#"+this.config.form).find("input[type='file']").eq(0).attr("id");
             document.getElementById(inputId).addEventListener("change", this._read, false);
             document.getElementById(this.config.dragArea).addEventListener("dragover", function(e){ e.stopPropagation(); e.preventDefault(); }, false);
             document.getElementById(this.config.dragArea).addEventListener("drop", this._dropFiles, false);
             document.getElementById(this.config.dragArea).addEventListener("drop", this._submit, false);
             document.getElementById(this.config.form).addEventListener("change", this._submit, false);
        } else
            console.log("Browser supports failed");
    }
    multiUploader.prototype._submit = function(e){
        e.stopPropagation(); e.preventDefault();
        self._startUpload();
    }
    multiUploader.prototype._preview = function(data){
        this.items = data;
        if(this.items.length > 0){
            var html = "";      
            var uId = "";
            for(var i = 0; i<this.items.length; i++){
                uId = this.items[i].name._unique();
                var sampleIcon = '<img src="images/icons/small/image.png" />';
                var errorClass = "";
                var msg="";
                if(typeof this.items[i] != undefined){
                    if(self._validate(this.items[i].type) <= 0) {
                        sampleIcon = '<img src="images/icons/small/alert.png" />';
                        errorClass =" invalid";
                        msg=" <span style='color: red'>Invalid File </span>";
                    } 
                    var sampleIcon = '';
                //  html += '<div class="dfiles'+errorClass+'" rel="'+uId+'"><div id="'+uId+'" class="progress" style="display:none; font-size: 11px"><a href="#">Edit Media</a></div><h5><b>'+sampleIcon+this.items[i].name+'</b> '+msg+'</h5></div>';
                }
            }
        //  $("#dragAndDropFiles").append(html);
        }
    }
    multiUploader.prototype._read = function(evt){
        if(evt.target.files){
            self._preview(evt.target.files);
            self.all.push(evt.target.files);
        } else 
            console.log("Failed file reading");
    }
    multiUploader.prototype._validate = function(format){
        var arr = this.config.support.split(",");
        return arr.indexOf(format);
    }
    multiUploader.prototype._dropFiles = function(e){
        e.stopPropagation(); e.preventDefault();
        self._preview(e.dataTransfer.files);
        self.all.push(e.dataTransfer.files);
    }
    multiUploader.prototype._uploader = function(file,f){
        if(typeof file[f] != undefined && self._validate(file[f].type) > 0){
            var data = new FormData();
            var ids = file[f].name._unique();
            data.append('file',file[f]);
            data.append('index',ids);
            $(".dfiles[rel='"+ids+"']").find(".progress").show();
            $.ajax({
                type:"POST",
                url:this.config.uploadUrl,
                data:data,
                cache: false,
                contentType: false,
                processData: false,
                success:function(rponse){
                    $("#"+ids).hide();
                    $("#filelist").append(rponse);
                    var obj = $(".dfiles").get();
                    $.each(obj,function(k,fle){
                        if($(fle).attr("rel") == rponse){
                            $(fle).slideUp("normal", function(){ $(this).remove(); });
                        }
                    });
                    if (f+1 < file.length) {
                        self._uploader(file,f+1);
                    }
                }
            });
        } else
            console.log("Invalid file format - "+file[f].name);
    }
    multiUploader.prototype._startUpload = function(){
        alert(this.all.length);
        if(this.all.length > 0){
            for(var k=0; k<this.all.length; k++){
                var file = this.all[k];
                this._uploader(file,0);
            }
        }
    }
    String.prototype._unique = function(){
        return this.replace(/[a-zA-Z]/g, function(c){
           return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
        });
    }
    this._init();
}
function initMultiUploader(){
    new multiUploader(config);
}

Now finally..i got the script to work for drag and drop interface and its perfect but am getting repetitions in the filelist it produces, infact it is uploading the files uploaded before again. I can explain....

Upload No.1 : a.png (these are the files i selected)
All the above mentioned files are uploaded and done perfectly.
Upload No.2 : b.png (this is the file i selected while uploading in the second round)

The expected output after the 2nd upload is naturally a.png, b.png right? but the output i am getting is a.png, a.png, b.png. It is showing the previous upload again and again. Can i anyone kindly this script for me please? I literally spent 5 days on this shit. I have already gone nuts. :(

Any help would be much appreciated! Thanks!

Dani AI

Generated

Short diagnosis (what's actually happening)

  • The uploader is being triggered multiple times (as suggested) and — more importantly — the upload queue (this.all) keeps every previous FileList batch. Each new drop adds another batch to this.all, so the next upload loop re-processes earlier batches and re-uploads old files.

Concrete, low-risk fixes

  • Snapshot-and-clear the queue at the start of an upload so previously handled batches are not re-processed. Example replacement for _startUpload:
multiUploader.prototype._startUpload = function(){
    if (!this.all || this.all.length === 0) return;
    var batches = this.all.slice(); // snapshot current batches
    this.all = [];                 // clear queue so old batches won't be re-uploaded
    for (var k = 0; k < batches.length; k++){
        this._uploader(batches[k], 0);
    }
}

Better file-queue management and de-dup

  • Push individual File objects into a single flat array (e.g. this.files) rather than pushing FileList objects. That makes deduplication and per-file removal trivial. Use a key like name + '_' + size + '_' + lastModified to skip duplicates when adding.

Validation and tiny bugs to fix

  • The current _validate checks are fragile: use arr.indexOf(format) !== -1 (or return boolean) instead of comparing to <= 0 / > 0 (index 0 is a valid match).
  • Replace typeof file[f] != undefined with typeof file[f] !== 'undefined' or simply if (file && file[f]).
  • Remove debug alert() calls and avoid attaching both a separate drop -> _submit listener and a drop -> _dropFiles listener; instead call _startUpload() from the end of _dropFiles once files are pushed.
  • Ensure the server returns a clear identifier (ID) that your success handler can match against each .dfiles[rel=...] entry before removing/adding UI elements.

Those changes (snapshot/clear queue, flatten+dedupe, correct validation checks, and simplifying event wiring) will stop re-uploads of previously processed files and eliminate the duplicated entries you see.

Member Avatar for Member #949455

The expected output after the 2nd upload is naturally a.png, b.png right? but the output i am getting is a.png, a.png, b.png. It is showing the previous upload again and again.

It's either you submit twice here:

document.getElementById(this.config.dragArea).addEventListener("drop", this._submit, false);
document.getElementById(this.config.form).addEventListener("change", this._submit, false);

It has something to do with this:

multiUploader.prototype._submit = function(e){
e.stopPropagation(); e.preventDefault();
self._startUpload();
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.