我的应用程序中有一个文件上传页面。我需要在文件上传时显示"正在上传",然后在文件处理时显示"正在处理"。然后在脚本完成后,我的页面被重定向到某个网址。
我尝试在脚本中使用 PHP SESSIONS。如下代码所示:
$_SESSION['uploaded']=0;
if (!empty($_FILES)) {
$tempFile = $_FILES['file']['tmp_name'];
$targetPath = dirname( __FILE__ ) . $ds. $storeFolder . $ds;
$_FILES['file']['name']=date('Ymdhis').$_FILES['file']['name'];
$targetFile = $targetPath. $_FILES['file']['name'];
if(move_uploaded_file($tempFile,$targetFile)){
$_SESSION['uploaded']=1;
//some processing here which takes some 4-5second to complete
}
}
文件上传完成后,我更新会话。我每秒通过在javascript中调用以下函数来检查会话:
function countdown(seconds){
console.log(<?php echo $_SESSION['uploaded']; ?>);
if(<?php echo $_SESSION['uploaded']; ?>==0){
setTimeout(function() {
//uploading
seconds--;
countdown(seconds);
}, 1000);
}
else{
//processing
}
}
从谷歌搜索了很长时间后,我才知道在单个脚本中,会话被锁定,直到脚本执行完成。然后我用了session_write_close();
但它也不起作用。我总是得到 0 个 SESSION 值。
请帮助我以最简单的方式找出解决方案。谢谢。
更新
也无法使其与 Ajax 请求一起使用。因此进一步尝试使用MySQL表。
我所做的是create table
何时调用上传脚本。然后使用以下代码在其中插入 status=0
的值:
$session=session_id();
$stmt=$conn->prepare("DROP TABLE IF EXISTS $session");
$stmt->execute();
$stmt=$conn->prepare("CREATE TABLE $session (id INT(11), status INT(11))");
$stmt->execute();
$stmt=$conn->prepare("INSERT INTO $session VALUES(1,0)");
$stmt->execute();
然后在上传完成后,我将状态更新为 1 并对文件进行处理。然后在成功完成脚本后,我重定向到结果页面并使用session_id()
删除表。
但是每秒检查状态的 My Ajax 脚本在上传.php脚本结束之前没有响应。我尝试在每次查询后关闭连接,但徒劳无功。获取状态的代码.php
<?php
session_start();
$session=session_id();
require_once('connect.php');
$stmt=$conn->prepare("SELECT * FROM $session WHERE id=1");
$stmt->execute();
$res=$stmt->fetch(PDO::FETCH_ASSOC);
echo $res['status'];
?>
直到现在都找不到解决方案。非常感谢帮助。谢谢。
与其每秒在服务器端调用一个 PHP 进程,不如使用静态文件来检查上传状态。
为客户端生成上传表单时:
- 为可访问的目录创建一个 tempnam客户。
- 将"上传"写入临时文件
- 将文件名存储在会话中。(请注意:用户可能会打开多个上传表单。将文件名存储在数组中(
- 将文件名作为隐藏字段发送到客户端。
在用户提交表单后的服务器端:
- 检查从客户端发送的文件名是否与会话中存储的文件名匹配。
- 将"处理"写入状态文件
- 在上传脚本结束时,将"已完成"写入状态文件
在客户端,用户提交表单后,通过对状态文件执行 ajax 请求来检查上传状态。
言论
使用 .htaccess 禁用状态文件的缓存。如果这不是选项,您可以使用 php 状态脚本实现相同的行为,并将上传状态保存到会话变量而不是状态文件中。
若要确保删除所有生成的文件,请注册一个销毁处理程序,该处理程序将删除会话中生成的文件: http://php.net/manual/en/function.session-set-save-handler.php
<?php echo $_SESSION['uploaded']; ?>
只被 PHP 预处理一次,就在将这个 JavaScript 发送到客户端之前。也就是说,客户端上的javascript看起来像:
function countdown(seconds){
console.log(0);
if(0==0){
setTimeout(function() {
//uploading
seconds--;
countdown(seconds);
}, 1000);
}
else{
//processing
}
}
你应该找到其他方法(ajax?(来更新客户端的信息。
这变得太长了,无法发表评论。
我不确定你会如何用 PHP 的进度信息来回应。我试过一次,失败了。
Socket.io 在 Node 中很棒.js并且有一个 PHP 服务器发射器。我可能会试一试。它应该提供近乎即时的通信,而无需等待脚本完成。
或者我会查看Jquery上传,它有一个PHP服务器脚本。支持进度条Jquery上传。要么直接实现它,要么查看源代码以了解如何显示进度信息。我试着快速浏览一下,但无法确定他们是如何轻松做到的。
可以在服务器上使用数据库,为什么要使用数据库?
为了节省带宽和数据库流量,您可以将进程分成 2 个文件
创建上传.php以提供上传过程
$_SESSION['uploaded']=0; if (!empty($_FILES)) { $tempFile = $_FILES['file']['tmp_name']; $targetPath = dirname( __FILE__ ) . $ds. $storeFolder . $ds; $_FILES['file']['name']=date('Ymdhis').$_FILES['file']['name']; $targetFile = $targetPath. $_FILES['file']['name']; if(move_uploaded_file($tempFile,$targetFile)){ // Save path to session var $_SESSION['uploaded']=$targetFile; //You can tell client if the uploading process were done and show 'Processing ...' // Place some code exit; } }
接下来,创建一个名为 progress 的文件.php
// check if(!empty($_SESSION['uploaded'])){ // Do your processing code here // Remove session unset($_SESSION['uploaded']); // Then send response to client after your processing were done echo 'Done'; exit; }
您可以在标记客户端时使用 jquery 重定向客户端。祝你好运