【发布时间】:2016-09-04 17:57:02
【问题描述】:
如果标题具有误导性,我很抱歉,没有简单的方法可以在标题中删减我的问题。我目前正在尝试 AJAX 文件上传;我之前已经完成了标准文件上传,但现在我试图通过添加一个进度条来使我的应用程序界面更好一点,该进度条跟踪文件上传进度并在视频完成上传、完成处理并放入数据库时通知用户。
除了 Ajax 当前正在为我的脚本完成执行之外,它工作得很好。基本上,发生的情况是大多数调用都是从一个名为uploadfiles.php 的文件中进行的。我正在使用带有feof 的while 循环并将进度记录到文件中,然后应该由另一个循环的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 常量
提前致谢。
【问题讨论】:
-
在您的问题中发布相关代码。
-
代码很长,你确定吗? @迈克
-
我添加了 pastebin 链接
-
这就是我说“相关”的原因