如何使PHP upload_progress会话工作?

php
2022-08-30 22:28:00

我试图在php中进行一系列更改后进行upload_progress会话.ini例如:

session.upload_progress.enabled = On

;session.upload_progress.cleanup = On

session.upload_progress.prefix = "upload_progress_"

session.upload_progress.name = "123"

session.upload_progress.freq =  "1%"

session.upload_progress.min_freq = "1"

并创建和基于html的页面,其中包含提交文件的表单:

<form action="upload_progress.php" method="POST" enctype="multipart/form-data">
  <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="123" />
  <input type="file" name="file1" />
  <input type="file" name="file2" />
  <input type="submit" />
</form>

然后是正确上传文件的服务器端脚本:

session_start();
move_uploaded_file($_FILES['file1']['tmp_name'], './uploads/'.$_FILES['file1']['name']);
move_uploaded_file($_FILES['file2']['tmp_name'], './uploads/'.$_FILES['file2']['name']);
print_r($_SESSION);

全局变量中有一个空数组,尽管文件上载已正确完成。会话设置有什么问题?$_SESSION

我使用的是 PHP 5.4.5

Notice: Undefined index: upload_progress_123 in C:\apache\localhost\www\upload_progress.php on line 13


答案 1

在PHP中通过会话上传进度非常棘手,并非所有上下文和情况都有很好的记录。 类似问题的数量表明会导致麻烦。我个人在这方面已经失去了一天多的时间,所以这是我的建议来帮助你。

  1. 明显的基本要求:PHP 版本 >= 5.4.0,PHP 作为 FastCGI 运行。(如何找出答案。)
  2. 为了更好地调试,请禁用即时会话属性清理,这样您就可以在上载完成后检查会话的内容php.ini
    session.upload_progress.cleanup = Off
  3. 找出会话的存储位置(变量在,Linux机器上的典型值是)并检查它们,查找在启动上传后命名的索引。session.save_pathphp.ini/var/lib/php/sessionsupload_progress_xxxxxxxxxxx

  4. 要激活特定的上传进度跟踪,通常使用隐藏的HTML表单元素。它必须在文件之前发送。如果你仔细想想,这是合乎逻辑的:当PHP处理请求时,它必须首先遇到信号,开始跟踪文件上传进度,然后识别文件本身。反过来,它不会起作用。

    <form action="upload_progress.php" method="POST" enctype="multipart/form-data">
        <input type="hidden" 
            name="<?php echo ini_get("session.upload_progress.name"); ?>" value="123" />
        <input type="file" name="myfile1" />
        <input type="submit" />
    </form>
    
  5. 仔细提交 AJAX。尽管不太可能,但某些 JS 库可能会更改 HTTP 请求中元素的顺序。您应该使用浏览器中的开发人员工具检查实际的HTTP通信,并确保发送元素的顺序与上一点一致。

  6. 会话名称。虽然您可以在代码中使用任何可能的会话名称,但 PHP 并不知道它,并且通常总是将上传进度写入默认会话(请查阅 您的 属性以检查实际值。此行为不是错误。
    如果您介意创建两个会话,则应更改代码以使用默认值,或者更改其默认值并不总是可能的(例如共享主机)。请注意,该值也可以通过 进行更改。PHPSESSIDphp.inisession.namesession.name.htaccess

  7. 一些PHP框架(Zend,Cake PHP)有自己的会话内容结构,PHP引擎在将上传进度写入会话时会损坏会话。导致存储信息丢失,从而导致注销,跟踪损坏等影响我得出的结论是,在这种情况下,必须使用2个不同的会话。

我的最终解决方案

我正在使用Zend框架,我最终得到了两个单独的会话。我使用以下纯PHP脚本来报告特定的文件上传进度。该脚本与 Zend Framework 完全隔离,并使用默认命名空间。PHPSESSID

session_start();

if(!isset($_GET['id']))
  die("unsupported");

$id = $_GET['id'];

if(!preg_match('/^[a-zA-Z0-9]{1,32}$/', $id))
  die("unsupported");

$sessionKey = ini_get('session.upload_progress.prefix') . $id;
$uploadInfo = (isset($_SESSION[$sessionKey])) ? $_SESSION[$sessionKey] : null;

$status  = [
    'total'    => 0,
    'current'  => 0,
    'rate'     => 0,
    'message'  => '',
    'done'     => false,
];

if($uploadInfo === null)
{
  header('Content-Type: application/json');
  echo json_encode($status);
  return;
}

$status = $uploadInfo + $status;
$status['total']   = $status['content_length'];
$status['current'] = $status['bytes_processed'];

$time = time() - $status['start_time'];
$status['rate'] = ($time > 0) ? $status['bytes_processed'] / $time : 0;

if (!empty($status['cancel_upload'])) {
    $status['done'] = true;
    $status['message'] = 'The upload has been canceled';
}

header('Content-Type: application/json');
echo json_encode($status);

在 Zend 框架之上创建的应用程序在 的方法中设置了自己的会话命名空间:Module.phponBootstrap()

$sessionManager = new \Zend\Session\SessionManager();
$sessionManager->setName('myFancyNamespace');
$sessionManager->start();

答案 2

上传进度可以在 $_SESSION Array 中看到,因此可以在另一个 php 请求中检查进度。

$_SESSION 将在上传文件之前可用,而不是在上传文件之后。所以一旦你处理了文件,它就会消失。您应该在上传文件时将其print_r单独的请求中。不在同一请求中。

就像这个例子一样

check_progress.php

<?php 
if(isset($_SESSION['upload_progress_123']))){
   print_r($_SESSION['upload_progress_123']);
}
?>

示例数组

<?php
$_SESSION["upload_progress_123"] = array(
 "start_time" => 1234567890,   // The request time
 "content_length" => 57343257, // POST content length
 "bytes_processed" => 453489,  // Amount of bytes received and processed
 "done" => false,              // true when the POST handler has finished, successfully or not
 "files" => array(
  0 => array(
   "field_name" => "file1",       // Name of the <input/> field
   // The following 3 elements equals those in $_FILES
   "name" => "foo.avi",
   "tmp_name" => "/tmp/phpxxxxxx",
   "error" => 0,
   "done" => true,                // True when the POST handler has finished handling this file
   "start_time" => 1234567890,    // When this file has started to be processed
   "bytes_processed" => 57343250, // Number of bytes received and processed for this file
  ),
  // An other file, not finished uploading, in the same request
  1 => array(
   "field_name" => "file2",
   "name" => "bar.avi",
   "tmp_name" => NULL,
   "error" => 0,
   "done" => false,
   "start_time" => 1234567899,
   "bytes_processed" => 54554,
  ),
 )
);

完整的教程可以在这里找到,如pilif所说

http://www.sitepoint.com/tracking-upload-progress-with-php-and-javascript/

http://oliversmith.io/technology/2011/12/04/php-5-4-file-upload-progress-and.html5-progress-bars/

也看到这个答案。PhP 5.4 中的 PhP 上传进度不起作用。未设置会话变量


推荐