问题
I'm trying to get the Session Upload Progress feature ( http://php.net/manual/en/session.upload-progress.php ) to work in Kohana. I have managed to get it working locally without Kohana using the following code:
<?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>
However when I use this code in Kohana (separating the PHP into a controller of course) the $_SESSION
variable does not get created for tracking the progress of the upload.
I believe this is something to do with how sessions in Kohana work. I cannot have session_start()
at the start of the script as it conflicts with the Kohana session that's already running. If I dump out the $_SESSION
or Session::instance()
contents the variable that should be added by the PHP Upload Progress functionality isn't there.
So how do I get the session variable to work with Kohana?
UPDATE
I have since created a clean install of Kohana to help narrow down on this issue. I have found that by not instantiating the Session
class in Kohana that I can use the code above and it works fine.
However when the Session
class is instantiated which it needs to be for my web application it stops working and the $_SESSION
variable containing upload progress is no longer created. This leads me to believe that the issue lies somewhere within how Kohana manages session information. I tried turning off the encryption with config settings but that didn't make a difference.
I'm using native session.
回答1:
Session cookie name has to be exactly the same as the one set in php config (session.name
), e.g.:
return array(
'native' => array(
'encrypted' => FALSE,
'name' => ini_get('session.name'),
),
);
If you don't want to use PHP's default session cookie name you will not get around this by setting the value during runtime, i.e. this won't work:
ini_set('session.name', 'my_kohana_session_name');
You will get around this by setting the value in your .htaccess file:
php_flag session.name "my_kohana_session_name"
This way you can keep the php.ini untouched but you can keep your custom cookie name for your Kohana application.
My tests proved that session encryption does not affect the upload progress information when using native session driver. That surely because the encryption is not used when using native driver regaldess the setting. ;)
PS. One thing I would also suggest - make sure that the ajax request is not cached. Had quite a few cases when it was cached and not showing fresh responses.
回答2:
I have found a solution.
What I have done is isolated the code that reads the PHP generated $_SESSION
variable into its own Controller
. In my case I have an AJAX controller for generic AJAX checks like validating emails, web URLs etc. The controller extends
from the default Controller
so that it does not inherit any session information from my custom controller (which is what my other controllers extend from).
So my new standalone Controller
looks like this:
<?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%" );
}
}
I use the same code as before for the actual form and make a minor tweak to the JavaScript, requesting this controller/action to retrieve the upload progress data. Problem solved!
来源:https://stackoverflow.com/questions/14437406/session-upload-progress