0

I'm attempting to convert this example which uses pure JavaScript to a JQuery equivalent.

The problem is that whenever I hit the upload button, it toggles the progress bar for the duration of the setTimeout function (1 second), then it disappears and displays "Done" having never shown me any actual progress.

I am using PHP > 5.4. I have session.upload_progress.enabled = On. I am uploading a huge file that I know should take several seconds to complete even locally.

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="//code.jquery.com/jquery-latest.min.js"></script>
<style>
#progress_bar {
  border: solid 1px #000;
  height: 20px;
  width: 300px;
  display: none;
}
#bar_color {
  background-color: #006666;
  height: 20px;
  width: 0px;
}
</style>
<title>File Upload Progress Bar</title>
</head>
<body>

<div id="progress_bar">
  <div id="bar_color"></div>
</div>
<div id="upload_status"></div>

<form id="uploadForm" enctype="multipart/form-data">
<input type="hidden" name="<?php echo ini_get('session.upload_progress.name'); ?>" value="uploadForm" />
<input type="hidden" name="MAX_FILE_SIZE" value="9999999" />
<input type="file" name="file" /><br />
<input type="submit" value="Start Upload" />
</form>

</body>
</html>

JQuery:

<script>
$(document).ready(function () {
    var interval;

    // update status bar
    $("#uploadForm").submit(function(e) {
        e.preventDefault();

        $('#progress_bar').toggle();
        interval = setInterval(function() {
            $.ajax({
                cache: false,
                url: "status.php",
                type: "GET"
            })
            .done(function(response) {
                if (response) {
                    $('#bar_color').width(response + '%');
                    $('#upload_status').html(response + '%');

                    if (response < 100) {
                        setInterval(interval, 1000);
                    } else {
                        $('#progress_bar').toggle();
                        $('#bar_color').width(0 + 'px');
                        $('#upload_status').html('Done.');
                        clearInterval(interval);
                    }
                }
            });
        }, 1000);
    });
});
</script>

PHP:

<?php
session_start();

$key = ini_get('session.upload_progress.prefix') . 'uploadForm';
if (!empty($_SESSION[$key])) {
    $current = $_SESSION[$key]['bytes_processed'];
    $total = $_SESSION[$key]['content_length'];
    echo $current < $total ? ceil($current / $total * 100) : 100;
} else {
    echo 100;
}

Where am I going wrong?

mister martin
  • 6,197
  • 4
  • 30
  • 63

1 Answers1

0

You have to upload the file with ajax and update the progress bar while it's uploading, not when it's done. http://jsfiddle.net/SwHf6/

$('input[type=file]').change(function() {
    var fd = new FormData();
    fd.append('file', $('input[type=file]').get(0).files[0]);

    $.ajax({
        url: '.',
        type: 'POST',
        processData: false,
        data: fd,
        xhr: function() {
            var xhr = $.ajaxSettings.xhr();
            xhr.upload.addEventListener('progress', function(ev) {
                $('.bar').css('width', (ev.loaded/(ev.total/100))+'%');
            }, false);

            return xhr;
        },
        beforeStart: function() {
            $('.bar').css('width', '0%');
        },
        success: function() {
            alert('done');
        }
    });
});
Ibrahim
  • 2,034
  • 15
  • 22
  • can you explain what's going on with your code? I don't understand it at all. – mister martin Apr 29 '14 at 15:17
  • First, that function will be executed on the onchange event of the file input, which is when you select a file. Then, it creates a new FormData object which is used to save and send to server the file from the file input. Then, it begins the ajax part, which will create an event that will be triggered multiple times while the file is uploading and with that you can get the bytes loaded to display the progress bar. – Ibrahim Apr 29 '14 at 21:26