【问题标题】:How to make PHP upload_progress SESSION work?如何使 PHP upload_progress SESSION 工作?
【发布时间】:2012-08-17 18:32:14
【问题描述】:

在对 php.ini 进行了一系列更改后,我正在尝试创建一个 upload_progress 会话:

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

【问题讨论】:

  • 你试过调试你的脚本吗?你的会话有效吗?你能设置一个$_SESSION 变量并正确读取它吗?您是否启用了错误日志记录,是否看到任何通知/警告?
  • 是的,会话工作正常,当然我已经尝试调试脚本,错误是在上面的问题中编辑的。第一次忘记添加了。

标签: php


【解决方案1】:

我知道这有点晚了,但也许这可以帮助其他人。

确保您已将 php.ini 中的 session.autostart 设置为“On”,不带引号。这对我来说是个问题,所以我得到一个空数组试图跟踪上传进度。

我使用 php 完成了上传工作。

请看:

https://github.com/TychaK/Track-Upload-Progress-using-Session-Upload-Progress-PHP-JavaScript-Ajax

我希望这可以帮助其他开发者:-)

【讨论】:

    【解决方案2】:

    如果您将 DockerCompose 与 NGINX 和 PHP 的单独容器一起使用,则会话 upload_progress_xxx 将不会更新。它仅适用于设置为“Apache x.x Handler”的 PHP Server API。

    我删除了 NGINX,只使用了官方的 PHP/Apache 镜像,现在它可以正常工作了。这是我的 Docker-Compose 文件:

    version: '3'
    services:
    
       php:
         image: "php:7.0-apache"
         ports:
           - "8080:80"
         volumes:
           - ./www:/var/www/
           - ./etc/php/php.ini:/usr/local/etc/php/php.ini
    

    【讨论】:

      【解决方案3】:

      在 PHP 中通过会话上传进度相当棘手,并非所有上下文和情况都有详细记录。 Numberofsimilarquestionsindicatesitcausestroubles。我个人在这方面已经失去了一天多的时间,所以这是我的建议来帮助你。

      1. 明显的基本要求:PHP 版本 >= 5.4.0 并且 PHP 作为 FastCGI 运行。 (How to find out.)
      2. 为了更好地调试,请在php.ini 中禁用即时会话属性清理
        session.upload_progress.cleanup = Off
        这样您可以在上传后检查会话的内容完成。
      3. 找出会话存储的位置(变量session.save_path in php.ini,Linux 机器上的典型值为/var/lib/php/sessions)并检查它们,在启动上传后查找名为upload_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 并不知道它并将上传进度始终写入默认会话,通常是 PHPSESSID(请参阅 php.ini 的属性 @987654342 @检查实际值。)This behavior is not a bug.
        如果您介意创建两个会话,您应该更改您的代码以使用默认值或更改session.name 的默认值,这并不总是可能的(例如共享主机)。请注意,该值也可以通过.htaccess 更改。

      7. 一些 PHP 框架(Zend、Cake PHP)有自己的会话内容结构,当将上传进度写入会话时,PHP 引擎会破坏会话。导致存储信息丢失,从而导致退出、跟踪损坏等影响Issueissueissue。 我得出的结论是,在这种情况下,必须使用 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 Framework 之上创建的应用程序在 Module.phponBootstrap() 方法中设置了自己的会话命名空间:

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

      【讨论】:

        【解决方案4】:

        上传进度可以在 $_SESSION 数组中看到,所以可以在另一个 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 Upload progress in PhP 5.4 is not working. Session variables not set

        【讨论】:

          【解决方案5】:

          在您的脚本调用move_uploaded_file() 和后续的print_r() 时,上传已经完成。

          如果你想获得上传进度,你必须

          • 将上传的表单提交到不同的浏览器窗口(以便您当前页面上的JS可以继续运行)或框架(使用表单上的target属性)
          • 使用 ajax 调用反复轮询服务器以查询当前会话的上传进度。

          http://php.net/manual/en/session.upload-progress.php的解释是指对同一个会话的不同请求,而不是同一个请求中的数据。

          出现了一些谷歌搜索http://www.sitepoint.com/tracking-upload-progress-with-php-and-javascript/,其中包含更多细节并提供复制和粘贴示例。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-05-08
            • 2017-11-14
            • 1970-01-01
            • 2012-11-12
            • 1970-01-01
            • 2019-04-10
            • 2012-11-23
            • 2017-06-19
            相关资源
            最近更新 更多