4

我正在尝试让会话上传进度功能(http://php.net/manual/en/session.upload-progress.php)在 Kohana 中工作。我已经设法让它在没有 Kohana 的情况下使用以下代码在本地工作:

<?php
    session_start();
    if (isset($_GET['progress']))
    {
        // does key exist
        $key = ini_get("session.upload_progress.prefix") . 'demo';
        if ( !isset( $_SESSION[$key] ) ) exit( "uploading..." );

        // workout percentage
        $upload_progress = $_SESSION[$key];
        $progress = round( ($upload_progress['bytes_processed'] / $upload_progress['content_length']) * 100, 2 );

        exit( "Upload progress: $progress%" );
    }
?>
<!doctype html>
<head>
</head>
<body>
    <section>
        <h1>Upload Form</h1>
        <form action="" method="POST" enctype="multipart/form-data" target="upload-frame">
            <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="<?php //echo $uid; ?>demo">
            <p>
                <label>File:</label>
                <input type="file" name="file" required="required">
            </p>
            <p><input type="submit" name="submit" value="Upload"></p>
        </form>

        <iframe id="upload-frame" name="upload-frame" width="1280" height="600"></iframe>

        <div id="file_upload_progress"></div>
    </section>

    <script src="jquery-1.7.1.min.js"></script>
    <script>
        $(document).ready(function() {

            var uploading = false;
            $('form').submit(function() {

                uploading = true;
                $('#upload-frame').one('load', function(){
                    uploading = false;
                });

                function update_file_upload_progress() {
                    $.get("?progress", function(data) {
                        $("#file_upload_progress").html(data);
                        if (uploading) {
                            setTimeout( update_file_upload_progress, 500 );
                        }
                    })
                    .error(function(jqXHR, error) { 
                        alert(error); 
                    });
                }

                // first call
                update_file_upload_progress();
            });
      });
    </script>
</body>
</html>

但是,当我在 Kohana 中使用此代码时(当然是将 PHP 分离到控制器中),$_SESSION不会创建变量来跟踪上传进度。

我相信这与 Kohana 中的会话如何工作有关。我不能session_start()在脚本的开头使用,因为它与已经运行的 Kohana 会话冲突。如果我转储$_SESSIONSession::instance()内容,则应由 PHP 上传进度功能添加的变量不存在。

那么如何让会话变量与 Kohana 一起使用呢?

更新

我已经创建了一个全新的 Kohana 安装来帮助缩小这个问题的范围。我发现通过不实例化SessionKohana 中的类,我可以使用上面的代码并且它工作正常。

但是,当Session实例化需要用于我的 Web 应用程序的类时,它会停止工作,并且$_SESSION不再创建包含上传进度的变量。这让我相信问题在于 Kohana 如何管理会话信息。我尝试使用配置设置关闭加密,但这并没有什么不同。

我正在使用本机会话。

4

2 回答 2

2

会话 cookie 名称必须与 php config ( ) 中设置的名称完全相同session.name,例如:

return array(
    'native' => array(
        'encrypted' => FALSE,
        'name'      => ini_get('session.name'),
    ),
);

如果您不想使用 PHP 的默认会话 cookie 名称,您将无法通过在运行时设置值来解决此问题,即这不起作用:

ini_set('session.name', 'my_kohana_session_name');

通过在 .htaccess 文件中设置值来解决此问题:

php_flag session.name "my_kohana_session_name"

这样,您可以保持 php.ini 不变,但您可以保留 Kohana 应用程序的自定义 cookie 名称。

我的测试证明,使用本机会话驱动程序时,会话加密不会影响上传进度信息。那肯定是因为在使用本机驱动程序时不使用加密设置。;)

PS。我还建议一件事 - 确保 ajax 请求没有被缓存。有很多情况下它被缓存并且没有显示新的响应。

于 2013-02-01T15:27:48.413 回答
1

我找到了解决方案。

我所做的是隔离将 PHP 生成的$_SESSION变量读取到它自己的Controller. 在我的情况下,我有一个 AJAX 控制器,用于通用 AJAX 检查,例如验证电子邮件、Web URL 等。extends默认的控制器,Controller因此它不会从我的自定义控制器(这是我的其他控制器扩展的)继承任何会话信息。

所以我的新独立Controller看起来像这样:

<?php defined('SYSPATH') or die('No direct script access.');

class Controller_Ajax extends Controller {

    public function action_upload_progress()
    {
            // get upload progress key
            $key = (!empty($_POST['key'])) ? $_POST['key'] : FALSE; 

            // start session to get PHP 5.4 generated $_SESSION variables
            session_start();

            // does key exist
            $key = ini_get("session.upload_progress.prefix") . $key;
            if ( !isset( $_SESSION[$key] ) ) {
                exit( "uploading..." );
            }

            // workout percentage
            $upload_progress = $_SESSION[$key];
            $progress = round( ($upload_progress['bytes_processed'] / $upload_progress['content_length']) * 100, 2 );
            exit( "Upload progress: $progress%" );
    }
}

我对实际表单使用与以前相同的代码,并对 JavaScript 进行小幅调整,请求此控制器/操作来检索上传进度数据。问题解决了!

于 2013-01-23T11:35:06.977 回答