Извините, если название вводило в заблуждение, нет простого способа сократить мою проблему в названии. В настоящее время я экспериментирую с загрузкой файлов AJAX; Раньше я выполнял стандартную загрузку файлов, но теперь я пытаюсь сделать интерфейс моего приложения немного лучше, добавив индикатор выполнения, который отслеживает ход загрузки файла и уведомляет пользователя, когда видео завершает загрузку, заканчивает обработку и помещается в базу данных.
Он работает в основном нормально, за исключением того факта, что Ajax в настоящее время работает над завершением выполнения моего скрипта. По сути, происходит то, что большинство вызовов выполняется из одного файла с именем uploadfiles.php
, Я использую цикл с feof
и запись прогресса в файл, который затем должен быть извлечен другим AJAX, который зацикливается, пока файл не сообщит ему, что запрос изменился / завершен.
Но, опять же, индикатор выполнения не перемещается, так как по какой-то причине первый AJAX-запрос ожидает uploadfiles.php
полностью завершает выполнение (Что произойдет, когда файл завершит загрузку, обработку и будет перемещен, что сделает индикатор выполнения бессмысленным), и из-за этого не пускает следующий AJAX-запрос, который извлекает содержимое файла журнала. Я пробовал следующее:
ob_start(); and ob_end_flush()
сразу после того, как файл перемещен из PHP-папки tmp в мою пользовательскую tmp-папкуflush()
Я полагаю, что это то же самое, что и пункт выше.Я также добавил ignore_user_abort()
чтобы гарантировать, что запрос не будет прерван, если пользователь покидает страницу / запрос заканчивается или прерывается.
** Вот код JS:
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);
}
}
Вот код PHP:
<?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);
Не беспокойся о Init.php
как (В этом случае) он используется только для PATH
постоянная
Заранее спасибо.
Используете ли вы сеансы на основе файлов PHP в файле Init.php (или в другом месте)? По умолчанию эти файлы блокируются до тех пор, пока сессия не будет эффективно закрыта, позволяя выполнять только один запрос за раз.
Если это так, вам нужно закрыть сеанс в файле загрузки с помощью:
session_write_close();
Других решений пока нет …