简体   繁体   中英

Update multiple progress bars when posting multiple files and form elements via ajax

How do you update multiple progress bars when posting a form via ajax? Here is the code I have but I can't figure it out:

Form code:

<form id="upload-form" class="no-padding" method="post" enctype="multipart/form-data">
    <p><label for="folder">Create folder:</label><input type="text" name="folder" placeholder="Enter a folder name"></p>
    <p><label for="file">Create file:</label><input type="text" name="file" placeholder="Enter a file name with extension (e.g. home.php)"></p>
    <p class="no-margin">Upload file(s):</p>
        <div class="custom-upload"> 
            <input id="upload" type="file" name="upload[]" multiple>
            <div class="fake-file">
                <a class="browse text-center"><i class="fa fa-list"></i> Browse</a><input placeholder="No file(s) selected..." disabled="disabled" >
            </div>
        </div>
    <div id="selectedFiles" class='selectedFiles'></div>
    <?php echo "<input name='url' hidden value='" . $_SERVER['REQUEST_URI'] ."'>";?>
    <button id="submit" name="submit"><i class="fa fa-upload"></i> Upload</button>
    <p id="uploading" class='success text-right' hidden>Please be patient while your files are uploading.</p>
</form>

Javascript code:

var selDiv = "";
document.addEventListener("DOMContentLoaded", init, false);
function init() {
    document.querySelector('#upload').addEventListener('change', handleFileSelect, false);
    selDiv = document.querySelector("#selectedFiles");
}

var files, filesToUpload;

// populates files into array (filesToUpload) and displays selected files to the user
function handleFileSelect(e) {
    if(!e.target.files) return;
    selDiv.innerHTML = "";
    var files = e.target.files;
    filesToUpload = Array.prototype.slice.call(files);
    if (files.length > 0) {
        selDiv.innerHTML += '<p id="file-upload-paragraph" class="no-padding no-margin">Files selected for upload. Click the <b>x</b> to cancel file upload for a specific file:</p>';
    }
    for(var i = 0; i < files.length; i++) {
        var f = files[i];
        selDiv.innerHTML += '<div class="selectedFiles"><a href="#" class="cancel text-center"><i class="fa fa-remove"></i></a><progress id="progress' + i + '" class="text-right" value="0" hidden></progress><span class="file-holder">' + f.name + ' <i class="fa fa-file"></i></span></div>';
    }
}

// removes user selected file before upload
$(document).on('click', '.cancel', function () {
    filesToUpload.splice($(".cancel").index(this), 1);
    $(this).closest('div').remove();
    if (filesToUpload.length == 0) {
        $('#file-upload-paragraph').remove();
        $('.custom-upload input[type=file]').val('');
    }
    $('.custom-upload input[type=file]').next().find('input').val(filesToUpload.length + ' files selected!');
});

// sets progress bar for each loaded file
$('#upload-form').submit(function(e){
    e.preventDefault();
    var url = location.href;
    $("#upload").remove();
    $(".cancel").hide();
    $("progress").show();
    var data = new FormData($('form')[0]);
    if (filesToUpload.length != 0) {
        for (var i = 0, j = filesToUpload.length; i < j; i++) {
            data.append("upload[]", filesToUpload[i]);
        }
    }
    $.ajax({
        url: url,
        type: 'POST',
        data: data,
        cache: false,
        contentType: false,
        processData: false,
        xhr: function(progress) { 
                for (var i = 0, j = filesToUpload.length; i < j; i++) {
                    var progressBar = 'progress' + i;
                    if(document.getElementById(progressBar) == null) {
                        j++;
                        continue;
                    }
                    var xhr = new XMLHttpRequest();
                    (function(progressBar) { 
                        xhr.upload.onprogress = function(e) {
                            $('#' + progressBar).attr({value: e.loaded, max: e.total});
                        };
                    }(progressBar));
                }
                return xhr;
             },
        success: function(res){
            if(!res.error) location.reload(true);
        }
    });
});

PHP code:

// function call
uploadFiles(count($_FILES["upload"]["name"]), $_FILES["upload"]["tmp_name"], $_FILES["upload"]["name"], $path);

// function that uploads selected files
function uploadFiles($total, $tmpFiles, $uploadedFiles, $path) {
    for($i=0; $i < $total; $i++) {
        $tmpFilePath = $tmpFiles[$i];
        if ($tmpFilePath != ""){
            $newFilePath = "$path/" . $uploadedFiles[$i];
            if(file_exists($newFilePath)) {
                unlink($newFilePath);
            }
            move_uploaded_file($tmpFilePath, $newFilePath);
        }
    }
}

Here is a picture of the form, just in case: Form image

Thanks in advance for any help.

I don't know if anyone will be looking to do the same thing but I found my own answer. Basically, replace my initial code for catching when the form is submitted with the following:

// sets progress bar for each loaded file
$('#upload-form').submit(function(e){
    e.preventDefault(); // removes the default behavior of the form button
    var url = location.href; // returns the current location
    $("#upload").remove(); // removes the file upload box which is replaced with an array in my other code
    $(".cancel").hide(); // hides the cancel buttons
    $("progress").show(); // shows the hidden progress bars

    // checks to see if files were selected for being uploaded
    if (filesToUpload.length != 0) {
        var progressBars = [];

        // this loop accounts for files that were deleted after selection
        for (var i = 0, j = filesToUpload.length; i < j; i++) {
            if(document.getElementById('progress' + i) == null) {
                j++;
                continue;
            }
            progressBars.push(i);
        }

        // call to postNext function
        postNext(0, progressBars, url);

    // executes when only the other form elements are submitted with no file upload
    } else {
        var data = new FormData($('form')[0]);
        $.ajax({
            url: url,
            type: 'POST',
            data: data,
            cache: false,
            contentType: false,
            processData: false,
            success: function(res){
                if(!res.error) location.reload(true);
            }       
        });
    }
});

// posts each file separately
function postNext(i, progressBars, url) {

    // continues as long as there are more files to display progress bars
    if (i < progressBars.length) {
        var index = progressBars[i];
        var data = new FormData($('form')[0]);

        // after first ajax send, resets form so only the remaining file uploads are resubmitted
        if (i == 0) {
            $("#upload-form")[0].reset();
        }
        data.append("upload[]", filesToUpload[i]); //append the next file
        $.ajax({
            url: url, // url for post
            type: 'POST',
            data: data, 
            cache: false,
            contentType: false,
            processData: false,
            xhr: function(progress) { 
                    // set the progress for a given progress bar
                    var xhr = new XMLHttpRequest();
                    var progressBar = 'progress' + index;
                    (function(progressBar) { 
                        xhr.upload.onprogress = function(e) {
                            $('#' + progressBar).attr({value: e.loaded, max: e.total});
                        };
                    }(progressBar));
                return xhr;
            },
            beforeSend: postNext(i + 1, progressBars, url) // begins next progress bar
        });
    }
}

// refreshes the page only after all ajax requests are completed
$(document).bind("ajaxSend", function () {
    console.log("waiting for all requests to complete...");
}).bind("ajaxStop", function () {
    location.reload(true);
});

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