I am sorry if the title was misleading, there is no easy way to abridge my issue in a title. I am currently experimenting with AJAX file uploads; I had done standard file uploads before but now I am trying to make my application's interface a bit better by adding a progress bar that tracks the file upload progress and notifies the user when the video finishes uploading, finishes processing and is put into the database.
It is working mostly fine, except for the fact that Ajax is currently working for my script to finish execution. Basically, what's happening is that most of the calls are made from a single file called uploadfiles.php
. I am using a while loop with feof
and logging the progress to a file, which is then supposed to be fetched by another AJAX that loops until the file tells it that the request has changed/completed.
But, again, the progress bar doesn't move as for some reason the first AJAX request is waiting until uploadfiles.php
fully finishes executing (Which would be when the file finishes uploading, processing and gets moved, and would make the progress bar pointless), and due to that doesn't let the next AJAX request that retrieves the log file contents. I have tried the following:
- Did
ob_start(); and ob_end_flush()
just after the file is moved from PHP's tmp folder to my custom tmp folder - Did
flush()
, which I suppose is the exact same thing as the point above - Echoed something random and flushed again, hoping something would happen
I have also added ignore_user_abort()
to ensure the request doesn't get aborted if the user leaves the page/the request ends or gets aborted.
**Here's the JS code:
function uploadFiles()
{
var data2 = new FormData($("#specialform")[0]);
timestamp = new Date().getUTCMilliseconds();
timestamp = timestamp.toString();
data2.append('outputId', timestamp);
console.log(data2);
$.ajax({
type : "POST",
url : "actions/uploadfiles.php",
data : data2,
processData : false,
contentType : false,
success: function(data)
{
alert('Finished first request');
getLog();
},
error: function (xhr, ajaxOptions, thrownError)
{
alert(xhr.responseText);
alert(thrownError);
},
xhr: function ()
{
var xhr = new window.XMLHttpRequest();
xhr.addEventListener("progress", function (evt)
{
if (evt.lengthComputable)
{
var percentComplete = evt.loaded / evt.total;
console.log(percentComplete);
var percentComplete = percentComplete * 100;
$("#progressBar").css({ width : percentComplete + '%' });
if ( percentComplete >= 100 )
xhr.abort();
}
else
console.log('unable to complete');
}, false);
return xhr;
},
})
.fail(function(data)
{
console.log(data);
});
//return {'error' : 'No files', 'result' : null};
}
function getLog()
{
if ( finished == false )
{
console.log("logs/" + timestamp);
$.ajax({
type : "GET",
url : "logs/" + timestamp,
processData : false,
contentType : false,
success: function(data)
{
if ( data == "processing" && !processed )
{
alert('processing video');
$("#progressBar").css({ 'background-color' : 'yellow' });
processed = true;
}
if ( data == "done" )
{
alert('finished conversion');
$("#progressBar").css({ 'background-color' : 'green' });
finished = true;
}
if ( $.isNumeric(data) )
$("#progressBar").css({ width : data + '%' });
console.log(data);
}
});
setTimeout(getLog, 1000);
}
}
Here's the PHP code:
<?php
require '../Init.php';
define('TMP_PATH', PATH.'/tmp');
define('V_STORE', PATH.'/resources/videos');
define('FFMPEG_PATH', 'F:/Webserver/ffmpeg/bin/ffmpeg.exe');
// ...
ob_start();
echo "END";
ob_end_flush();
flush();
// ...
$remote = fopen($_FILES['file']['tmp_name'], 'r');
$local = fopen($filename, 'w');
$read_bytes = 0;
set_time_limit(28800000);
ignore_user_abort(true);
$interval = 0;
while( !feof($remote) )
{
$buffer = fread($remote, 2048);
fwrite($local, $buffer);
$read_bytes += 2048;
$progress = min(100, 100 * $read_bytes / $filesize);
if ( $interval <= 0 )
{
file_put_contents('../logs/'.$logFile, $progress);
$interval = 1000;
}
else
$interval--;
}
// ...
$proc = popen(FFMPEG_PATH.' -i '.$filename.' -b '.$newBitrate.' '.V_STORE.'/'.$video_id.'.mp4', 'r');
while (!feof($proc))
{
file_put_contents('../logs/'.$logFile, fread($proc, 4096));
}
file_put_contents('../logs/'.$logFile, "done");
sleep(5);
unlink('../logs/'.$logFile);
Don't worry about the Init.php
as (In this case) it is only used for the PATH
constant
Thanks in advance.