php - 如何使 PHP upload_progress SESSION 工作?

标签 php

在 php.ini 中进行了一系列更改后,我正在尝试使工作成为 upload_progress session ,例如:

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 全局变量中有一个空数组,尽管文件上传已正确完成。 session 设置有什么问题?

我正在使用 PHP 5.4.5

注意:C:\apache\localhost\www\upload_progress.php 第13行未定义索引:upload_progress_123

最佳答案

在 PHP 中通过 session 上传进度相当棘手,并且并非所有上下文和情况都得到了很好的记录。 Number of similar questions indicates it causes troubles .我个人为此损失了一天多的时间,所以这是我的建议,可以帮助您。

  1. 明显的基本要求:PHP 版本 >= 5.4.0 并且 PHP 作为 FastCGI 运行。 ( How to find out. )
  2. 为了更好地调试,请在 php.ini 中禁用即时 session 属性清理
    session.upload_progress.cleanup = Off
    This way you can check the contents of a session after the upload is done.
  3. Find out where session are being stored (variable session.save_path in php.ini, typical value on linux machines is /var/lib/php/sessions) and inspect them, look for an index named upload_progress_xxxxxxxxxxx after upload is initiated.

  4. To activate a particular upload progress tracking usually a hidden HTML form element is used. It must be sent before the file. If you think about it it's logical: when PHP is processing the request it must first encounter the signal to start tracking the file upload progress and after that recognize the file itself. The other way around, it won't work.

    <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. session 名称。虽然您可以在代码中使用任何可能的 session 名称,但 PHP 并不知道它并将上传进度始终写入默认 session ,通常是PHPSESSID(请参阅您的 php.ini 的属性 session.name 检查实际值。)This behavior is not a bug.
    如果您介意正在创建两个 session ,您应该更改代码以使用默认值或更改 session.name 的默认值,这并非总是可行(例如共享主机)。请注意,也可以通过 .htaccess 更改该值。

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

我的最终解决方案

我使用的是 Zend Framework,我结束了两个单独的 session 。我使用以下纯 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 Framework 之上制作的应用程序在 Module.phponBootstrap() 方法中设置它自己的 session 命名空间:

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

关于php - 如何使 PHP upload_progress SESSION 工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12071358/

相关文章:

php - 有太多的 php 标签

php - 上传文件到服务器时在MySQL数据库中保存文件路径

php - CodeIgniter post_controller_constructor Hook 运行两次?

php - 尝试执行 youtube 分析 API 时获取 'Forbidden error'

php - Codeigniter:将数据从 Controller 传递到 View

javascript - 如何在进一步执行 js 之前从循环中收集 $.get 的所有结果

php - 抓取网站并获取表格数据

php - 如何从具有不同where条件的表中添加和减去数据

php - MySql 查询两个日期时间范围之间每个间隔的记录

php - Moodle - 获取当前用户角色