18

在对 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

5 回答 5

5

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

  1. 明显的基本要求:PHP 版本 >= 5.4.0 且 PHP作为 FastCGI 运行。(如何发现。
  2. 为了更好地调试禁用即时会话属性清理php.ini
    session.upload_progress.cleanup = 关闭
    这样,您可以在上传完成后检查会话的内容。
  3. 找出 session 的存储位置(变量session.save_pathin 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的属性session.name以检查实际值。)这种行为不是错误。
    如果您介意创建两个会话,您应该更改您的代码以使用默认值,或者更改session.name并非总是可能的默认值(例如共享主机)。请注意,该值也可以通过 更改.htaccess

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

我的最终解决方案

我正在使用 Zend Framework,最后我得到了两个单独的会话。我使用以下纯 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.php'sonBootstrap()方法中设置了它自己的会话命名空间:

$sessionManager = new \Zend\Session\SessionManager();
$sessionManager->setName('myFancyNamespace');
$sessionManager->start();
于 2016-12-09T11:30:42.373 回答
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 5.4 中的 PhP 上传进度不起作用。未设置会话变量

于 2016-02-23T07:37:24.913 回答
0

在您的脚本调用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/,其中包含更多细节并提供复制和粘贴示例。

于 2015-09-10T15:43:18.280 回答
0

如果您将 DockerCompose 与 NGINX 和 PHP 的单独容器一起使用,则不会更新会话 upload_progress_xxx。它仅适用于设置为“Apache xx 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
于 2018-06-07T11:16:11.240 回答
0

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

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

我使用 php 取得了工作上传进度。

请参见:

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

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

于 2018-06-21T08:00:02.343 回答