如何使PHP upload_progress SESSION工作?

时间:2012-08-22 10:43:08

标签: php

我正在尝试在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

4 个答案:

答案 0 :(得分:3)

通过PHP会话上传进度非常棘手并非所有上下文和环境都有详细记录。 Number of similar questions indicates it causes troubles。我个人在这方面失去了一天以上,所以我的建议是帮助你。

  1. 明显的基本要求:PHP版本&gt; = 5.4.0,PHP 作为FastCGI运行。 (How to find out.
  2. 为了更好地调试,请在php.ini
    session.upload_progress.cleanup = Off
    中禁用立即会话属性清理这样,您可以在上传完成后检查会话的内容。
  3. 找出存储会话的位置(session.save_path中的变量php.ini,linux机器上的典型值为/var/lib/php/sessions)并检查它们,查找名为{{的{ 1}}上传后启动。

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

    upload_progress_xxxxxxxxxxx
  5. 小心提交AJAX。虽然不太可能,但某些JS库可能会更改HTTP请求中元素的顺序。您应该使用浏览器中的开发人员工具检查实际的HTTP通信,并确保发送的元素的顺序与前一点一致。

  6. 会话名称。虽然您可以在代码中使用任何可能的会话名称,但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> (请咨询您的PHPSESSID' s属性php.ini来检查实际值。)This behavior is not a bug.
    如果您介意创建两个会话,则应更改代码以使用默认值或更改session.name的默认值,这并非总是可行(例如,共享托管)。请注意,该值也可以通过session.name更改。

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

  8. 我的最终解决方案

    我正在使用Zend Framework,最后我有两个单独的会话。我使用以下普通的PHP脚本来报告特定的文件上载进度。该脚本与Zend Framework完全隔离,并使用默认的.htaccess命名空间。

    PHPSESSID

    在Zend Framework之上创建的应用程序在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); 的{​​{1}}方法中设置了自己的会话命名空间:

    Module.php

答案 1 :(得分:1)

上传进度可以在$ _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

答案 2 :(得分:0)

如果您将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 :(得分:0)

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

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

我使用php进行了有效的上传。

请参阅:

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

我希望这对其他开发人员有所帮助:-)