I'm using PHP version 5.3.2 on both my local development server and remote web server.
I'm trying to use uploadify to upload several files to the server. In the receiving script, I would like to use data stored in the session, however because uploadify sends files to the script using flash it doesn't send the session cookie.
The workaround for this problem is to get uploadify to GET or POST the session id to the script, however I'm finding this very unreliable.
In my script I have the following:
<?php
ini_set('session.use_only_cookies', FALSE);
ini_set('session.use_trans_sid', TRUE);
session_name('SESSNAME');
session_start();
print_r($_SESSION);
The script url is something like script.php?SESSNAME=sessionid and I have tried using transparent session ids as above and also manually setting the id using session_id($_GET['SESSNAME']).
This always works when accessing the script directly with the browser and sending the current session id along, even if I manually delete the session cookie. It also always works with uploadify on my local server. However when using uploadify on the remote server, it works about 20% of the time, completely randomly. There is no pattern. It seemed to work with greater frequency when I added
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 1);
to the script, however this may have been just coincidence.
Local server info: http://www.dur.ac.uk/n.r.brook/info_local.php
Remote server info: http://www.dur.ac.uk/n.r.brook/info.php
Doing some digging around and looking at the headers the script is receiving, I think I may have determined the issue.
You need to send the session id when using uploadify because flash does not send cookies when using the FileReference.upload() (I think!) method. However, as well as the session id, in load balanced environments (such as the remote server) there is also the BALANCEID cookie which determines which server the user is currently working with. Flash doesn't send this cookie so the load balancer sometimes sends the request to a different server, and on this server the session does not exist.
I have tested this behaviour by setting a session variable after I have printed the session. Doing this and repeatedly sending files exhibits the issue - at first I get an empty array, but a few repeats in the variable starts appearing.
So, if the above is all true, then my question is what can I do to get flash to send this data with the upload so the load balancer knows which server to use? Or is this a lost cause?
After further research, I found the following post - http://swfupload.org/forum/generaldiscussion/977
This suggests there is no way cookies can be sent with FileReference.upload() and therefore uploadify cannot be used with load balanced servers if you want to use session data. However, I think I will now attempt a solution which saves data linked to the session id to a file. The uploadify receiving script can open this file and pull out the required data.
This is my first experience working with anything Flash based, it has not improved my opinion of the technology!
My solution to this problem is:
In the 'upload' page:
file_put_contents($some_folder.'/'.session_id(), serialize($just_the_vars_you_will_be_using));
In your javascript that loads uploadify:
var start = document.cookie.indexOf("PHPSESSID=");
var end = document.cookie.indexOf(";", start); // First ; after start
if (end == -1) end = document.cookie.length; // failed indexOf = -1
var cookie = document.cookie.substring(start+10, end);
$('#fileInput').uploadify({
'uploader' : 'uploadify.swf',
'script' : 'uploadify.php',
'cancelImg' : 'cancel.png',
'auto' : true,
'multi' : true,
'scriptData': { SESSID : cookie }
});
In the script that receives the files:
$vars = unserialize(file_get_contents($some_folder.'/'.$_POST['SESSID']));
If you want to write back to the 'session' in this script, at the end:
file_put_contents($some_folder.'/'.$_POST['SESSID'], serialize($vars));
As far as I know, there shouldn't be any security issues associated with this, as you will only be using a handful of variables stored in the file (I only store an incrementing value and a temporary file path). Make sure there is an index.html in $some_folder to prevent file listing.