Forum Moderators: coopster
I'm new here and would appreciate any assistance! I've run into a fatal error on my web project and I'm not quite sure if the error lies in my (probably extremely poor) coding or in the PHP configuration.
I am currently making a script to allow users to upload images into a directory, and then list the directory contents so they can use the information to see what images are hosted (so they can then use the images in an article).
The script for uploading pictures seems to be working fine (with smaller files), as does the directory listing part. However, I was thinking "well, someone may want to upload a photo, and you know what photos are like these days with these 3,412.6 megapixel camerawotsits and so on, so I thought I'd up the max file size that can be uploaded to ~3mb.
Testing this with a nice 2.5mb file, I very quickly ran into the following error:
Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 12288 bytes) in /public_html/uploader.php on line 64
I looked at around line 64, and it turns out that where I'd taken the photo uploading script from another area of my site, I'd left in a couple if/then statements setting new variables. Being redundant checks and variables, I removed these, cursed my silly self for the 100th time today, and tried again, this time with success. I then upped the file size limit to ~5mb and it now uploads 5mb pics without error.
Which means the problem is fixed, right? Except it's bugging me still. All those lines did were set a few variables that would end up not being used... if they can cause that error, who knows what other lax bit of coding I've done that's going to bring the site to its knees?
I've looked into the problem and all advice seems to point towards the memory_limit of the php.ini configuration - I use a hosting company however that doesn't allow me access to the php.ini (I'm not exactly too ambitious in my plans right now!) so I can't adjust this. Some of my research has suggested the error can be down to bad code leaks etc? I'm running a very very small mysql DB with my site so there's not a crazy amount for the site to do except for this particular bit where I upload images to it!
Here's the area of code around line 64. Line 64 in particular is the one marked with ***s, and I've highlighted (with // comments) the redundant code that once removed fixed the problem (obviously the *s are not there in the code I used on the site):
$sent = $_POST["sent"];
if ($sent == "yes") {
if ((($_FILES["file"]["type"] == "image/gif")
¦¦ ($_FILES["file"]["type"] == "image/jpeg")
¦¦ ($_FILES["file"]["type"] == "image/pjpeg")
¦¦ ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 3146000))
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
}
else
{
// redundant code start!
$uploadedfile = $_FILES['file']['tmp_name'];
if ($_FILES["file"]["type"] == "image/gif") { $extension = ".gif"; $src = imagecreatefromgif($uploadedfile); }
*** if ($_FILES["file"]["type"] == "image/jpeg") { $extension = ".jpg"; $src = imagecreatefromjpeg($uploadedfile); }
if ($_FILES["file"]["type"] == "image/pjpeg") { $extension = ".jpg"; $src = imagecreatefromjpeg($uploadedfile); }
if ($_FILES["file"]["type"] == "image/png") { $extension = ".png"; $src = imagecreatefrompng($uploadedfile); }
// redundant code end!
$directory1 = "uploads/" . "$usn" . "/";
if (!file_exists($directory1)) { mkdir($directory1, 0777); }
move_uploaded_file($_FILES["file"]["tmp_name"], $directory1 . $_FILES["file"]["name"]);
Thanks for any and all help and suggestions, I'll happily post more of my code if requested to fix this!
It is the creation of your image from jpeg that is giving you fits, I'm certain. Although the file size in and of itself may only be a certain size, the function requires more memory than just the size of the file itself.
Some helpful (required) reading from past threads regarding similar issues:
More PHP image upload problems [webmasterworld.com]
Uploading big images turn to black! [webmasterworld.com]
Memory usage when rotating photos in PHP [webmasterworld.com]
Presumably you want to call imagecreatefromjpeg() in order to create a smaller web-displayable image?
I just finished a project for the exact same reasons you stated - the client wanted to allow up to 10MB file uploads to be resized to "reasonable" sizes for final storage because his users don't understand images and would load them directly from their cameras. When resized, the humongous files are overwritten with the resized version and a thumb is created.
You can try fiddling with the .htaccess per-directory to allow PHP to slurp up more memory and increase the timeout, and it will work - the problem with that is it then becomes a laborious task on your server, eating up memory with every upload. On a busy site, it may cause a crash.
The solution lies in Imagick. PHP's Imagick uses ImageMagick to process images, which has two advantages:
- The image manipulation is an external process, so it doesn't require that PHP takes up more memory.
- ImageMagick does it's own memory management, so if it's using more memory than allocated is does so on virtual disk (unverified, the exact methods may differ from my obtuse description, but the bottom line is ImageMagick doesn't hog your system memory.)
You may still have to up the timeout setting via .htaccess for large files, but this works very very well when you step outside PHP defaults. Additionally, ImageMagick has *TONS* more options you can't do with GD that involve image compositing, truetype manupulation, filters, and even manages non-web file formats, such as uploaded CMYK images.
But it can be a bear to get it installed right. :-( You need to a) install ImageMagick binaries, then b) Install the appropriate extensions for Imagick, none of which I understand; I had my admin do it for me. He hates me now. :-)
Torrid Story of Huge Files Using GD [webmasterworld.com]
Sample of difficulties with Imagick [webmasterworld.com] Learn from my mistakes and consider the obvious FIRST! :-)
Well penders, the code was left in there by mistake so actually wasn't doing anything (well obviously it was, but it wasn't *meant to be*) - but yeah, I think the way things are going I'm going to have to use the function in this form to create a 'thumbnail' version at some point - so looks like I'm limiting the file size back down again!
And thanks for the Imagick tip rocknbil, I'll definitely keep it in mind but right now I think it's a step beyond me and I'm not sure just how technical my hosts are so I'm not gonna trust them with it just yet either!
Thanks for all your help everyone!
If you're getting fatal memory errors, unless you're on a dedi/VPS, this could produce some serious problems for you if you keep upping the memory limit per .htaccess - your host may pull your plug. :-)