Page 1 of 1

Can't upload files even though settings are correct

Posted: Tue Nov 13, 2007 3:30 pm
by iandunn
I've got a form to upload a file, but if I try to upload anything larger than 2MB it fails with $_FILES['userfile']['error'] being set to 1, which means the file was larger than the limit set in upload_max_filesize. My upload_max_filesize is set to 10M, though, as well as post_max_size and the form's max_file_size. The source is below and you can try it for yourself here. The values in the grey box @ the bottom are being pulled from ini_get(), so that shows that the values are set correctly. I've done a lot of searching but can't find any reason why it would say that the limit is 10MB, but that a 2MB file is over the limit. It's running under IIS, so it isn't the RequestBodyLimit issue.

Code: Select all

<html>
<head>
	<title>PHP upload test</title>
	
	<style>
		
		.errorBox
		{
			border: 1px solid black;
			padding: 5px 5px 5px 5px;
			width: 300px;
			margin-bottom: 30px;
			color: red;
		}
		
		.infoBox
		{
			margin-top: 50px;
			background-color: #C0C0C0;
			width: 200px;
			padding: 5px 5px 5px 5px;
			border: 1px solid black;
		}
		
	</style>
</head>
<body>

<?php

	$uploadErrorCodes = array(
		0 => "There is no error, the file uploaded with success",
		1 => "The uploaded file exceeds the upload_max_filesize directive in php.ini",
		2 => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form",
		3 => "The uploaded file was only partially uploaded",
		4 => "No file was uploaded",
		6 => "Missing a temporary folder",
		7 => "Failed to write file to disk.",
		8 => "File upload stopped by extension"
	);

	// Uncomment this section to force PHP values
	// upload_max_filesize, post_max_size and max_input_time cannot be set with ini_set
	$iniSetErrors = array();
	if(!ini_set('display_errors', '1'))
		array_push($iniSetErrors, 'display_errors');
	if(!ini_set('error_reporting', E_ALL))
		array_push($iniSetErrors, 'error_reporting');
	if(ini_get('memory_limit') != '')
		if(!ini_set('memory_limit', '12M'))
			array_push($iniSetErrors, 'memory_limit');
	if(!ini_set('max_execution_time', '160'))
		array_push($iniSetErrors, 'max_execution_time');
		
	
	if(count($iniSetErrors) > 0)
	{
		echo '<div class="errorBox">The following PHP directives couldn\'t be set:<br />';
		foreach($iniSetErrors as $iniSetError)
			echo $iniSetError . '<br />';
		echo 'Safe mode is <strong>'. ini_get('safe_mode') .'</strong>';
		echo '</div>';
	}
	
	// If file was uploaded, print $_FILES
	if(isset($_POST['upload-submit']))
	{
		$uploadError = $_FILES['userfile']['error'];
		$filesArray = print_r($_FILES, true);
		
		if($uploadError != 0)
			$filesArray = str_replace("[error] => ". $uploadError, "[error] => ". $uploadError . " - ". $uploadErrorCodes[$uploadError], $filesArray);
		
		echo '<p><pre>$_FILES '. $filesArray . '</pre></p>';
	}
	
	// Upload form
	echo '
		<form enctype="multipart/form-data" action="" method="POST">
		    <input type="hidden" name="max_file_size" value="10000000" />
		    Send this file: <input name="userfile" type="file" />
		    <input type="submit" name="upload-submit" value="Send File" />
		</form>
	';
	
	// PHP directives any other relevant information
	$max_file_size = isset($_POST['max_file_size']) ? $_POST['max_file_size'] : '';
	echo sprintf('
		<div class="infoBox">
			file_uploads: %s<br />
			upload_max_filesize: %s<br />
			post_max_size: %s<br />
			memory_limit: %s<br />
			max_input_time: %s<br />
			max_execution_time: %s
			form max_file_size: %s<br />
		</div>
		',
		ini_get('file_uploads'),
		ini_get('upload_max_filesize'),
		ini_get('post_max_size'),
		(ini_get('memory_limit') == '' ? 'N/A' : ini_get('memory_limit')),
		ini_get('max_input_time'),
		ini_get('max_execution_time'),
		($max_file_size == '' ? 'N/A' : $_POST['max_file_size'])
	);
	
?>

</body>
</html>

Posted: Tue Nov 13, 2007 6:59 pm
by feyd
Unfortunately, ini_set() doesn't actually affect the upload size settings in php.ini, which are read prior to your script being parsed during the upload process. You need to tweak those settings elsewhere, like in an .htaccess file.

Posted: Tue Nov 13, 2007 8:22 pm
by Christopher
Have you narrowed it down to what is actually failing. Is there an error before your script starts, or is it happening somewhere in your script?

You understand that if you don't move the temporary file that PHP creates to some location that PHP will remove it.

Posted: Wed Nov 14, 2007 8:50 am
by iandunn
feyd, I know that. I'm not using ini_set to set directives that it cant...

Code: Select all

// Uncomment this section to force PHP values 
   // upload_max_filesize, post_max_size and max_input_time cannot be set with ini_set
   $iniSetErrors = array();
   if(!ini_set('display_errors', '1'))
      array_push($iniSetErrors, 'display_errors');
   if(!ini_set('error_reporting', E_ALL))
      array_push($iniSetErrors, 'error_reporting');
   if(ini_get('memory_limit') != '')
      if(!ini_set('memory_limit', '12M'))
         array_push($iniSetErrors, 'memory_limit');
   if(!ini_set('max_execution_time', '160'))
      array_push($iniSetErrors, 'max_execution_time');
arborint,
but if I try to upload anything larger than 2MB it fails with $_FILES['userfile']['error'] being set to 1, which means the file was larger than the limit set in upload_max_filesize.
There aren't any runtime errors, just $_FILES['userfile']['error'] being == to 1. This script is a general purpose one to make sure all the upload settings are correct, not to actually use in production, so there's no need to move the file anywhere. I want it to be deleted.

Posted: Wed Nov 14, 2007 12:40 pm
by iandunn
It looks like even though phpinfo() and ini_get are telling me that the directives are set to higher than the default, they're really not. I upped the default upload_max_filesize to 8M and now I can upload up to that, but if I go over it errors out. I've got the max_input_time set @ 240 seconds, but it still stops @ 60 (the default).

This is a Windows server running IIS6 and PHP 5.2. I'm using the registry to override the default values. Putting a custom php.ini in the directory didn't work, and that's a sloppy method anyway. Any ideas on why PHP is saying that the values are being overridden, but they really aren't?