contact
Remember me
No account yet? Register

How to Properly Secure an Image Upload on Websites with PHP + Flash Pitfalls and how to use PHP Thumbnailer

I am about to explain and show an example of how to properly secure your website against malicious uploads with your image uploader. I will also demonstrate how to use the PHP Thumbnailer created by Ian Selby. The PHP Thumbnailer can be obtained from http://www.gen-x-design.com/projects/php-thumbnailer-class/.

I take no credit for what I am about to explain. I am just trying to spread the word further. For the original sources of what I am talking about please see: http://www.scanit.be/uploads/php-file-upload.pdf , http://www.mysql-apache-php.com/fileupload-security.htm.
Basically, the number one truth to the internet for web developers is to never trust the data that is sent to the server from any processed form from the user, no matter what. Anyone with a brain in web development can create a CGI script to mimic the inputs of the original site with malicious intent (See the Scanit document for an example).

The main question is: “how do we securely handle an uploaded file?” Well, nothing is ever fully secure. The theory I like to say is: “If a human can program it or create it, then another human can reverse engineer or crack it.” That theory is true for so many things in life, from computers to machines and so many other things that we create.

On to the example:
First thing we should do with an uploaded image file is verify to see if it is a valid image. We can do that by implementing several security measures in the PHP file that handles the uploaded data.

Here we are checking the file size to make sure it does not bypass the limit we want.

if ($_FILES[’Filedata’][’size’] > 800000 )
{
$tmpMes = “Image file to big”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}
//check if its image file

One security measure we can take with PHP is to use getimagesize(), to see if it actually is an image file. Be warned though, the method is not full proof. As explained in the ScanIt document, an image file can be both a valid image file and PHP script. An image file such as GIF and JPGs can contain comment sections in the file. In that section a malicious coder can insert PHP script to compromise your server’s security. Basically, the malicious attacker can specify the header information of the sent file to be a GIF, JPG, or PNG, but at the same time he can tell the actual file name to be a .php file. Now, when he submits the GIF or JPG as a .php the php file will still be considered a valid image file, but the attacker will then gain the opportunity to go to the file and start a malicious attack, once the image has been uploaded. When he goes to the file via the URL, PHP will recognize the image file as a PHP file since it has a .php extension and PHP will ignore the actual image data. (See the ScanIt document for examples of the actual malicious code in action)

if (!getimagesize($_FILES[’Filedata’][’tmp_name’]))
{
$tmpMes = “Invalid image file…”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

The next step we can take to make sure it is a valid image file is to create an array full of blacklisted extensions. We then loop through each object in the array and check it against the actual file names extension. So, even if the user passes it as a gif but still give the file name any of the extension we listed the file will be refused. Still, it is not secure enough even with this.

$blacklist = array(”.php”, “.phtml”, “.php3″, “.php4″, “.php5″, “.js”, “.shtml”, “.sh”,”.pl” ,”.py”, “.asp”, “.aspx”, “.jsp”, “.cgi”);
foreach ($blacklist as $file)
{
if(preg_match(”/$file\$/i”, $_FILES[’Filedata’][’name’]))
{
$tmpMes = “Upload of Executable Files is Forbidden!”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}
}

We then check the image mime type to see if it is an image file that we want. Again, this method is not secure enough as people can still fake the mime type of the file, even though we read it in as an actual image file with getimagesize().

$imageinfo = getimagesize($_FILES[’Filedata’][’tmp_name’]);
if($imageinfo[’mime’] != ‘image/png’ && $imageinfo[’mime’] != ‘image/jpeg’ && $imageinfo[’mime’] != ‘image/jpg’) {
$tmpMes = “Only JPEG and PNG image formats allowed”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

We are going to now take it a step further and check to make sure the file name actually has an image format extension that we allow. We fill an array with the allowed formats. Then we extract the extension from the file name and search our array to see if it matches any of our extensions. If it does we continue on happily. If it doesn’t we return false thus terminating the process. Even though we checked above to make sure it wasn’t an invalid format we really didn’t check to make sure it was the format we wanted. It never hurts to double check when it comes to security.

$allowedEXT = array(”.jpg”, “.jpeg”, “.png”);

$ext = strrchr($_FILES[’Filedata’][’name’],’.');

if(in_array($ext, $allowedEXT))
{
$tmpMes = “Correct Format”;
$_SESSION[’tmpmes’] = $tmpMes;
}
else
{
$tmpMes = “Invalid Format”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

The next step we can take to improve security is to create a random file name for the file so the user that submitted will not be able to access it based on the original file name.

$sess = session_id();
$upFiles[’tmpsrc’] = $sess.”_”.$_FILES[’Filedata’][’name’];

Above, we use the current session id as part of the file name. If you want to improve security even more you could do the following
(
$sess = session_id();
$upFiles[‘tmpsrc’] = crypt($sess, $_FILES[‘Filedata’][‘name’]).$ext;
)

We basically took the sessions id put it into crypt() with the filename as part of the second crypt method to make it an even stronger encryption. Since, we already know the extension of the file we then can just tack it on to the end, thus creating a totally random file name with no relation to the original name whatsoever.

Now why am I using $_SESSION to store the file name and the actual file name? I am using it so that I can access the file until we have gathered all of the other necessary data before we add it to the database.

$_SESSION[’tmpsrc’] = $upFiles[’tmpsrc’];
$_SESSION[’tmpname’] = $_FILES[’Filedata’][’name’];

$upFiles[’tmpname’] = $_FILES[’Filedata’][’name’];

We now move the uploaded file from the temporary PHP folder to a more permanent area based on the random file name we gave it earlier.

if(move_uploaded_file($_FILES[’Filedata’][’tmp_name’], “uploadtmp/”.$upFiles[’tmpsrc’]))
{
}
else
{
$tmpMes = “Failed to process image file.”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

Now doing this brings me to my next point. Never, have a folder with 777 permissions, because you are allowing full access to all the files in that directory on your server, so even if somehow a malicious file still gets through the users will be able to browse the folder and access it.

I was trying to find a way for the flash uploader I created to maintain access to the files so I could do “< .img src="img file location" ./.>” and have it displayed, but at the same time limit access to the folder so users would get a forbidden message when trying to access anything other than an image file.

The solution I found was quite simple really. Thanks to http://www.mysql-apache-php.com/fileupload-security.htm I was able to find a solution that fit my needs. Basically there are 2 ways to keep images access secure and it all depends on your server accessibility for administration purposes.

Most shared hosting you will not have access to set the ownership of folders. Therefore, your best option is to store all the images in a secure folder not in the root of your website directory, doing so will not allow someone to access it just by browsing via URLS in the browser. You then make sure only your PHP files have access to it for writing purposes. (See the above link for more information) To improve security even further of that one folder you should add an .htaccess file to the folder that contains:

AddHandler cgi-script .php .php3 .php4 .php5 .phtml .pl .py .jsp .asp .htm .shtml .sh .cgi .aspx
Options -ExecCGI

< .files ^(*.jpeg|*.jpg|*.png)./> remove the periods at the front and the end!
order deny,allow
deny from all

The first 2 lines stop the execution of the following files. The next few lines only allow the jpeg, jpg, and png formats to read and accessed.

However, using this method you cannot just do < .img src=”img file” ./>. Instead, you will have to use your server’s graphics library to dynamically read the file in and insert it. There are cons and pros to using this method. One of the biggest pros is that the user will never ever know the file name. Another pro is that you will be storing the filenames in a database so that you can access them later. Notwithstanding, the biggest con to this method can be server performance. If you have lots and I do mean lots of visitors per minute and have a lot of images to display you can potentially bog down the server, thus bottle-necking your websites performance. Why does it bottleneck you ask? Well, using this method the server has to open the image file with its image library then process it to be inserted into the html dynamically. (See http://www.mysql-apache-php.com/fileupload-security.htm on how to implement this feature fully)

I knew this method would not work for me, since I could potentially have over 1 million visitors on the site at the same time. Plus, the site accesses a lot of images at the same time. Luckily, I have my own dedicated server, so I have access to setting who owns folders and such. What you do is, set the folder group permission to only allow apache to access it (that is if your server has apache on it) and give the folder a 770 permission. Doing so, will allow you to store the folder in your web root and be able to have people access it via < .img src=”image file” ./>. Yet, at the same time people will not be able to write or execute files in the folder. When the try to access other files in that folder or the folder itself, they will receive an “Access Forbidden” message. I then took even more precautions by including the .htaccess files in the folders to help prevent and secure it even more, just in case. (See http://www.mysql-apache-php.com/fileupload-security.htm for more details on this method)

Part 2 Processing the Image with PHP Thumbnailer

Since, I am using a custom programmed flash upload to upload the images, I had to find a way to process the image in another location, but at the same time be able to send an Ajax response back to update the window dynamically.

One of the biggest problems I ran into was believe it or not but Flash will not send the session ID in FireFox to the server when uploading. I browsed around and people mentioned including the session ID in the html itself. Well, I couldn’t do this, because I was dynamically updating the area and the index page had already been loaded, plus it is possible to compromise security putting the sessionID in the html. So the problem was one: When flash uploaded it created an entirely new session with new session variables; two: how do I get the session id to flash to send when uploading?

The solution I came up with was to use Ajax to my advantage and Javascript. The following code will demonstrate what I did.

Flash Code:

First thing we do in flash is create callbacks to javascript functions, so flash can receive data from an Ajax request. Then we call our xajax_acquireFlashID() javascript function to start a Asynchronous call to php to get the current session ID and send it back. (Yes, I am using Xajax. It is a powerful and simple to use Ajax library for php. Xajax easly blows the pants off of Sajax for simplicity and ease of use, but still just as powerful.)


Note: I am using Action Script 3.0. The code will not work with Flash 8 or action script 2.0.

if (ExternalInterface.available)
{
try{
ExternalInterface.addCallback(”flashCallBack”, updateStatus);
ExternalInterface.addCallback(”idCallBack”, acquireID);
ExternalInterface.call(”xajax_acquireFlashID”);
} catch(error:SecurityError)
{
} catch(error:Error)
{
}
}

We then create our functions that will handle the callback of our javascript external interface. (Please, for the love of goodness, never ever use this syntax in Actionscript 3.0:

acquireID = function(value:string)
{
};

The above is a poor practice when it comes to Actionscript 3.0 and object orientated programming. Plus, flash will throw errors on it.
)

function acquireID(value:String)
{
flashID = value;
}

function updateStatus(value:String)
{
tx_status.text = value;
}

Next we create our URLHandler (no more using getURL). You now have to use the more object oriented methods.

var uploadURL:URLRequest = new URLRequest();
uploadURL.url = “upload_handler.php”;

Then right before we start the upload we finish up creating our URLRequest. We basically put it in the upload click and then check to make sure we do have an actual session ID. We then create a piece of post data to be sent along with the uploaded file.

function upload_click(event:MouseEvent)
{
if (selected_file == undefined) {
tx_status.text = (”Please select a file to upload.”);
} else {
if(flashID != “”)
{
//Create variable to send in post method
var idVariable:URLVariables = new URLVariables();
idVariable.sessID = flashID;
//Assign our variables to the data so it can be sent.
uploadURL.data = idVariable;
//Make sure the upload method is set to POST
uploadURL.method = URLRequestMethod.POST;
//Begin Upload
file.upload(uploadURL);
}
else
{
tx_status.text = “Browser not supported”;
}
}
}

Now how will we know the file has been sent? We create an event listener onto the FileReference Object.

var file = new flash.net.FileReference();
file.addEventListener(Event.CANCEL, cancelFile);
file.addEventListener(Event.COMPLETE, completeFile);
file.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpError);
file.addEventListener(IOErrorEvent.IO_ERROR, IOERROR);
file.addEventListener(Event.OPEN, openFile);
file.addEventListener(ProgressEvent.PROGRESS, progressFile);
file.addEventListener(SecurityErrorEvent.SECURITY_ERROR, SecureERROR);
file.addEventListener(Event.SELECT, selectFile);

Now we create our function to handle the newly defined event for Event.Complete. We also send an external call so that we can send an Ajax request to our PHP to let us know that we can now process the image.

function completeFile(event:Event) {
tx_status.text = “Upload Complete… Processing Image.”;
if (ExternalInterface.available)
{
ExternalInterface.call(“xajax_processIMG”);
}
resetUpload();
}

Note: These are only snippets of code, not the entire thing to make it work out of the box. You will have to figure the rest out yourself.

Now we move on to the javascript functions for the callbacks for flash:

Javascript Code:

We create a helper function so we can get a flash movie by its name for easier access.

function thisMovie(movieName) {
if (navigator.appName.indexOf(”Microsoft”) != -1) {
return window[movieName];
} else {
return document[movieName];
}
}

Now we create our callback functions that flash will receive data from. Pretty self explanatory, and that’s it for the callback functions for javascript. Simple, right?

function flashCallBack(value) {
thisMovie(”upload_reg”).flashCallBack(value);
}

function idCallBack(value) {
thisMovie(”upload_reg”).idCallBack(value);
}

Now onto the main guts for the PHP part:

PHP Code:

We create our function that Xajax will call, that we set up, for processing the Image file with PHP Thumbnailer. The function will then be called by flash, through Xajax, when the upload is complete. (See in line comments for more information)

function processIMG()

{
//html templating processing
require_once(’generateHTML.php’);
//Include the PHP Thumbnailer file
include_once(’thumbnail.inc.php’);
//create a new Xajax response
$objectResponse = new xajaxResponse();
//Right, good thing we stored the filename into the $_SESSION variable from the first part to access it. Since, this code is in a completely separate file which Xajax connects to.
//We check to make sure that we haven’t lost the file name
if(isset($_SESSION[’tmpsrc’]))
{
//Now we create a new instance of the Thumbnail class and give it the location for the image
$i1 = new Thumbnail(’uploadtmp/’.$_SESSION[’tmpsrc’]);
//Checking to see if the image is greater than 800px by 600px. If it is we resize it with thumbnailer to a more suitable size for the large image. Then we save it with a new filename.
if($i1->getCurrentWidth() >= 800 || $i1->getCurrentHeight() >= 600)
{
$i1->resize(800,600);
$i1->save(’uploadtmp/resized_’.$_SESSION[’tmpsrc’]);
}
//If it is not bigger than 800px by 600px then we just go ahead and save the file with the new filename we want
else
{
$i1->save(’uploadtmp/resized_’.$_SESSION[’tmpsrc’]);
}
//The beauty of the PHP Thumbnailer is that you do not have to reload the file once you have saved it to resize it again. We then resize it down to the thumbnail size we want and save it with a new name.
$i1->resize(120,160);
$i1->save(’uploadtmp/thumb_’.$_SESSION[’tmpsrc’]);
//We are using the 4.0 php version of thumbnailer so we need to destroy our instance after we are finished.
$i1->destruct();
//Generate template html code to contain the image
$imgBox = generate_imgRegister(’uploadtmp/thumb_’.$_SESSION[’tmpsrc’]);
//We then destroy the original temporary file, since we have created 2 new files.
unlink(”uploadtmp/”.$_SESSION[’tmpsrc’]);
//Finally we create a response to Ajax to assign the $imgbox html into the innerHTML of a div that is currently on the users screen.
$objectResponse->Assign(’uploadform’, ‘innerHTML’, $imgBox);
}
//if we cannot access the $_SESSION variable with the file name we need to tell Xajax to start another request that will send the error info back to the user in the flash player.
else
{
$objectResponse->Script(”xajax_uploadStatus();”);
}
//Return which ever $objectResponse we filled depending on the If Statement, so Xajax can process it and update the html as needed.
return $objectResponse;
}

Now we create the function that will send the current Session Id back to our Flash file. Flash will call this function through Xajax upon loading.

function acquireFlashID()
{
//New response object for Xajax
$objectResponse = new xajaxResponse();

//Get the current session ID
$sess = session_id();
//Create the response which actually calls the javascript that sends the data to Flash. We insert the ID as the variable in the javascript function.
$objectResponse->Script(”idCallBack(’”.$sess.”‘);”);
//Return the response so Xajax can process it
return $objectResponse;
}

We now create the other xajax function which sends the upload error back to be displayed in the flash player.

function uploadStatus()
{
//New response object for Xajax
$objectResponse = new xajaxResponse();

//Check to see if we have an error message that was created when processing upload
if(isset($_SESSION[’tmpmes’]))
{
$objectResponse->Script(”flashCallBack(’”.$_SESSION[’tmpmes’].”‘);”);
}
//if we don’t then somehow we lost the $_SESSION variables. So just let the user know we failed to process the image properly.
else
{
$objectResponse->Script(”flashCallBack(’Failed to process image’);”);
}
//Return the Xajax response so it can be processed
return $objectResponse;
}

Now you are probably going to ask: “Wait, where do we process the session Id from flash?” Well where we handled the upload of course! Back to the upload code:

Original Code:
if ($_FILES[’Filedata’][’size’] > 800000 )
{
$tmpMes = “Image file to big”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

//check if its image file
if (!getimagesize($_FILES[’Filedata’][’tmp_name’]))
{
$tmpMes = “Invalid image file…”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

$blacklist = array(”.php”, “.phtml”, “.php3″, “.php4″, “.php5″, “.js”, “.shtml”, “.sh”,”.pl” ,”.py”, “.asp”, “.aspx”, “.jsp”, “.cgi”);
foreach ($blacklist as $file)
{
if(preg_match(”/$file\$/i”, $_FILES[’Filedata’][’name’]))
{
$tmpMes = “Upload of Executable Files is Forbidden!”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}
}

$imageinfo = getimagesize($_FILES[’Filedata’][’tmp_name’]);
if($imageinfo[’mime’] != ‘image/png’ && $imageinfo[’mime’] != ‘image/jpeg’ && $imageinfo[’mime’] != ‘image/jpg’) {
$tmpMes = “Only JPEG and PNG image formats allowed”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

$allowedEXT = array(”.jpg”, “.jpeg”, “.png”);

$ext = strrchr($_FILE[’Filedata’][’name’],’.');

if(in_array($ext, $allowedEXT))
{
$tmpMes = “Correct Format”;
$_SESSION[’tmpmes’] = $tmpMes;
}
else
{
$tmpMes = “Invalid Format”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

$sess = session_id();
$upFiles[’tmpsrc’] = $sess.”_”.$_FILES[’Filedata’][’name’];

$_SESSION[’tmpsrc’] = $upFiles[’tmpsrc’];
$_SESSION[’tmpname’] = $_FILES[’Filedata’][’name’];

$upFiles[’tmpname’] = $_FILES[’Filedata’][’name’];

if(move_uploaded_file($_FILES[’Filedata’][’tmp_name’], “uploadtmp/”.$upFiles[’tmpsrc’]))
{
}
else
{
$tmpMes = “Failed to process image file.”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

$tmpMes = “Upload Successful”;

$_SESSION[’tmpmes’] = $tmpMes;

session_write_close();

return true;

Now let’s see what it looks like when we add the code to get the session ID from flash.

New Code:
//Checking for the post variable that we sent
if (isset($_POST[’sessID’]))
{
//If it exists then we link it up with the current session and start the session
session_id($_POST[’sessID’]);
session_start();
//Determining if we are located in the correct upload area of the site
if(isset($_SESSION[’regview’]))
{
if($_SESSION[’regview’] == “1″)
{
if ($_FILES[’Filedata’][’size’] > 800000 )
{
$tmpMes = “Image file to big”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

//check if its image file
if (!getimagesize($_FILES[’Filedata’][’tmp_name’]))
{
$tmpMes = “Invalid image file…”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

$blacklist = array(”.php”, “.phtml”, “.php3″, “.php4″, “.php5″, “.js”, “.shtml”, “.sh”,”.pl” ,”.py”, “.asp”, “.aspx”, “.jsp”, “.cgi”);
foreach ($blacklist as $file)
{
if(preg_match(”/$file\$/i”, $_FILES[’Filedata’][’name’]))
{
$tmpMes = “Upload of Executable Files is Forbidden!”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}
}

$imageinfo = getimagesize($_FILES[’Filedata’][’tmp_name’]);
if($imageinfo[’mime’] != ‘image/png’ && $imageinfo[’mime’] != ‘image/jpeg’ && $imageinfo[’mime’] != ‘image/jpg’) {
$tmpMes = “Only JPEG and PNG image formats allowed”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

$allowedEXT = array(”.jpg”, “.jpeg”, “.png”);

$ext = strrchr($_FILE[’Filedata’][’name’],’.');

if(in_array($ext, $allowedEXT))
{
$tmpMes = “Correct Format”;
$_SESSION[’tmpmes’] = $tmpMes;
}
else
{
$tmpMes = “Invalid Format”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

$sess = session_id();
$upFiles[’tmpsrc’] = $sess.”_”.$_FILES[’Filedata’][’name’];

$_SESSION[’tmpsrc’] = $upFiles[’tmpsrc’];
$_SESSION[’tmpname’] = $_FILES[’Filedata’][’name’];

$upFiles[’tmpname’] = $_FILES[’Filedata’][’name’];

if(move_uploaded_file($_FILES[’Filedata’][’tmp_name’],”uploadtmp/”.$upFiles[’tmpsrc’]))
{
}
else
{
$tmpMes = “Failed to process image file.”;
$_SESSION[’tmpmes’] = $tmpMes;
return false;
}

$tmpMes = “Upload Successful”;

$_SESSION[’tmpmes’] = $tmpMes;

session_write_close();

return true;
}
}
}

Now all should be good right? Wrong! One of the common pitfalls is that we told flash to access upload_handler.php when uploading, but yet we are on index.php in an Ajax area. So, when flash uploads, even though we told the previous index.php to session_write_close(),upload_handler.php will not be able to write our new variables to the session file! Why is that you may ask. Well, index.php has already opened and maintained the connection to the session file; Therefore only one area can access the session file at a time since PHP locks the file.

Even though the file uploaded properly and we have a temporary file that we moved to the folder in the upload code, we will not be able to access when flash sends the request to process the image. Why? Because, when flash sent the processIMG function, the processIMG function is trying to access $_SESSION[‘tmpsrc’] but it will not be able access the $_SESSION[‘tmpsrc’] since it won’t even exist!

I tried to solve this for hours until I realized the solution. The solution:

PHP Code:
We are still going to use upload_handler.php and we will add the following to it at the very bottom on the first if statement:
Else
{
start_session();
}

Next instead of having flash call the upload_handler.php we are going to put it into index.php, but we are going to put it with services.php where we call all of our other php files to include;
So if you have session_start(); in services.php you need to remove it and in its position put: require_once(‘upload_handler.php’);
Now on the index we are calling require_once(‘services.php’); . So, now when the index.php loads it will acquire the upload_handler code, and if it does not see any post data then we start the session normally. Otherwise, we have an incoming image file being uploaded.

Now in flash we need to change 1 line:
In flash where you see( uploadURL.url = “upload_handler.php”;) change it to: (uploadURL.url = “http://www.yourdomain.com/” or if you want to specify the index.php do uploadURL.url = “http://www.yourdomain.com/index.php”).

Flash will now call the index.php which still contains our code for processing images, but now it will not lock the session file since we are still calling it from the index.php instead of upload_handler.php. Thus, your $_SESSION variables will now be saved correctly, and it will not create a new session when uploading.

Are we done? No! If you understand how Ajax works and that if you try to process a request which interacts with the Session file, it will then be locked by the Ajax PHP file. Therefore, when we originally sent the xajax_processIMG command from flash upon completion, more than likely we are still processing the uploaded image file on the server in our upload_handler! Why? Because when flash closes its connection to the server it raises the Event.COMPLETE event. Which then we called our external interface to call xajax_processIMG. Now, that we called it and we are still processing the image file in upload_handler the xajax_processIMG will collide with the upload_handler $_SESSION variables, in a sense, thus causing you to lose all your $_SESSION variables in upload_handler! In reality what is happening, is that the Ajax function is being called faster than we can process with upload_handler. Basically, the Ajax Function PHP is locking the Session file to it, and not allowing the upload_handler.php file to access the session file!

How do we solve this you may ask? In our flash file we need to set up a timeout feature to allow the upload_handler.php to write its data and free up the session file first.

Flash Old Code:
function completeFile(event:Event) {
tx_status.text = “Upload Complete… Processing Image.”;
if (ExternalInterface.available)
{
ExternalInterface.call(“xajax_processIMG”);
}
resetUpload();
}
Flash New Code:

We basically take part of the original code and move it to a new function which we then set a timeout on for execution.

function completeFile(event:Event) {
tx_status.text = “Upload Complete… Processing Image.”;
//We are making it so after 1 second has passed (depends on how fast your server is) before we run the function procIMG() which will then call our external interface to call xajax_processIMG. At the same time we update the text on the flash player letting the user know the upload was successful and we are processing the image.
setTimeout(procIMG,1000);
resetUpload();
}

function procIMG()
{
if(ExternalInterface.available)
{
ExternalInterface.call(”xajax_processIMG”);
}
}

Are we done? Yes, yes we are the upload should now work flawlessly, though you may have to adjust the timeout settings in flash depending on your server speed and number of users using it.

I hope you learned something from all this, since doing this almost drove me up the wall working on it for hours into the early morning trying to figure out why my variables were not saving =|.

Pages
    Categories