I am using Cakephp as my framework. I have a problem in uploading my files through a form. I am using an Uploader plugin from THIS website.
My php ini file has this piece of code.
upload_max_filesize = 10M
post_max_size = 8M
this is from uploader.php --> plugin file has
var $maxFileSize = '5M'; //default max file size
In my controller.php file, i use this code to set max file size as 1 MB at runtime.
function beforeFilter() {
parent::beforeFilter();
$this->Uploader->maxFileSize = '1M';
}
In the uploader.php, we perform this ...
if (empty($this->maxFileSize)) {
$this->maxFileSize = ini_get('upload_max_filesize'); //landmark 1
}
$byte = preg_replace('/[^0-9]/i', '', $this->maxFileSize);
$last = $this->bytes($this->maxFileSize, 'byte');
if ($last == 'T' || $last == 'TB') {
$multiplier = 1;
$execTime = 20;
} else if ($last == 'G' || $last == 'GB') {
$multiplier = 3;
$execTime = 10;
} else if ($last == 'M' || $last == 'MB') {
$multiplier = 5;
$execTime = 5;
} else {
$multiplier = 10;
$execTime = 3;
}
ini_set('memore_limit', (($byte * $multiplier) * $multiplier) . $last);
ini_set('post_max_size', ($byte * $multiplier) . $last); //error suspected here
ini_set('upload_tmp_dir', $this->tempDir);
ini_set('upload_max_filesize', $this->maxFileSize); //landmark 2
EXPECTED RESULT:
When i try uploading a file that is 2MB of size, it shouldn't take place because maxFileSize is 1MB at run time. So upload should fail.
THE PROBLEM IS :
But it is getting uploaded.
Landmark 1 does not get executed. (in comments)... land mark 2 does not seem to work...
upload_max_filesize does not get the value from maxFileSize.
Please help me... thank you
Setting upload_max_filesize during the script execution is rather pointless, since by the time the script executes the file is already uploaded and accepted by the server. If you need to reject the file based on size in your script (as opposed to Apache or PHP rejecting it), you need to evaluate the size of the uploaded file and "manually" ignore it if it's too big.
pointless or not it's not even possible to change upload_max_filesize with ini_set.
upload_max_filesize has the changable flagPHP_INI_PERDIR wich means Entry can be set in php.ini, .htaccess, httpd.conf or .user.ini (since PHP 5.3)
as a additional comment remember that post_max_size should be equal or greater then upload_max_filesize
Related
I have changed the php.ini file and added a set_time_limit(0) on the top of my page and i still cant upload big files with php. I am also using ajax and javascript to upload, and i can upload 400Mb files. i was trying to upload a 3.2GB file on WAMP.
My code:
<?php
set_time_limit(0);
session_start();
include('../Connect/Connect.php');
$User = $_SESSION['User'];
$Files = $_FILES['File'];
if(isset($User))
{
if(!empty($Files))
{
for($X = 0; $X < count($Files['name']); $X++)
{
$Name = $Files['name'][$X];
$TMP = $Files['tmp_name'][$X];
move_uploaded_file($TMP, '../Users/' . $User . '/' . $Name);
}
}
}
else
{
header("location:../");
}
header("location:index.php");
$Connect->close();
?>
check your browser, that it supports >2 GB files
set POST_MAX_SIZE higher than UPLOAD_MAX_FILESIZE (ofcourse set
normal values in settings, not like memory_limit 10 000GB....
max_input_time set for example to 30000
check x64 or x86 OS/Browser
had on debian with php 5.3.21 error, that it does not allow >2GB files cause of bug in PHP -> it just gives u a chance that u may get
php version with wrong atoi() and atol() converting.
When using
ini_get("upload_max_filesize");
it actually gives you the string specified in the php.ini file.
It is not good to use this value as a reference for the maximum upload size because
it is possible to use so-called shorthandbytes like 1M and so on which needs alot of additional parsing
when upload_max_filesize is for example 0.25M, it actually is ZERO, making the parsing of the value much harder once again
also, if the value contains any spaces like it is interpreted as ZERO by php, while it shows the value without spaces when using ini_get
So, is there any way to get the value actually being used by PHP, besides the one reported by ini_get, or what is the best way to determinate it?
Drupal has this implemented fairly elegantly:
// Returns a file size limit in bytes based on the PHP upload_max_filesize
// and post_max_size
function file_upload_max_size() {
static $max_size = -1;
if ($max_size < 0) {
// Start with post_max_size.
$post_max_size = parse_size(ini_get('post_max_size'));
if ($post_max_size > 0) {
$max_size = $post_max_size;
}
// If upload_max_size is less, then reduce. Except if upload_max_size is
// zero, which indicates no limit.
$upload_max = parse_size(ini_get('upload_max_filesize'));
if ($upload_max > 0 && $upload_max < $max_size) {
$max_size = $upload_max;
}
}
return $max_size;
}
function parse_size($size) {
$unit = preg_replace('/[^bkmgtpezy]/i', '', $size); // Remove the non-unit characters from the size.
$size = preg_replace('/[^0-9\.]/', '', $size); // Remove the non-numeric characters from the size.
if ($unit) {
// Find the position of the unit in the ordered string which is the power of magnitude to multiply a kilobyte by.
return round($size * pow(1024, stripos('bkmgtpezy', $unit[0])));
}
else {
return round($size);
}
}
The above functions are available anywhere in Drupal, or you can copy it and use it in your own project subject to the terms of the GPL license version 2 or later.
As for parts 2 and 3 of your question, you will need to parse the php.ini file directly. These are essentially configuration errors, and PHP is resorting to fallback behaviors. It appears you can actually get the location of the loaded php.ini file in PHP, although trying to read from it may not work with basedir or safe-mode enabled:
$max_size = -1;
$post_overhead = 1024; // POST data contains more than just the file upload; see comment from #jlh
$files = array_merge(array(php_ini_loaded_file()), explode(",\n", php_ini_scanned_files()));
foreach (array_filter($files) as $file) {
$ini = parse_ini_file($file);
$regex = '/^([0-9]+)([bkmgtpezy])$/i';
if (!empty($ini['post_max_size']) && preg_match($regex, $ini['post_max_size'], $match)) {
$post_max_size = round($match[1] * pow(1024, stripos('bkmgtpezy', strtolower($match[2])));
if ($post_max_size > 0) {
$max_size = $post_max_size - $post_overhead;
}
}
if (!empty($ini['upload_max_filesize']) && preg_match($regex, $ini['upload_max_filesize'], $match)) {
$upload_max_filesize = round($match[1] * pow(1024, stripos('bkmgtpezy', strtolower($match[2])));
if ($upload_max_filesize > 0 && ($max_size <= 0 || $max_size > $upload_max_filesize) {
$max_size = $upload_max_filesize;
}
}
}
echo $max_size;
Here is the full solution. It takes care of all traps like the shorthand byte notation and also considers post_max_size:
/**
* This function returns the maximum files size that can be uploaded
* in PHP
* #returns int File size in bytes
**/
function getMaximumFileUploadSize()
{
return min(convertPHPSizeToBytes(ini_get('post_max_size')), convertPHPSizeToBytes(ini_get('upload_max_filesize')));
}
/**
* This function transforms the php.ini notation for numbers (like '2M') to an integer (2*1024*1024 in this case)
*
* #param string $sSize
* #return integer The value in bytes
*/
function convertPHPSizeToBytes($sSize)
{
//
$sSuffix = strtoupper(substr($sSize, -1));
if (!in_array($sSuffix,array('P','T','G','M','K'))){
return (int)$sSize;
}
$iValue = substr($sSize, 0, -1);
switch ($sSuffix) {
case 'P':
$iValue *= 1024;
// Fallthrough intended
case 'T':
$iValue *= 1024;
// Fallthrough intended
case 'G':
$iValue *= 1024;
// Fallthrough intended
case 'M':
$iValue *= 1024;
// Fallthrough intended
case 'K':
$iValue *= 1024;
break;
}
return (int)$iValue;
}
This is what I use:
function asBytes($ini_v) {
$ini_v = trim($ini_v);
$s = [ 'g'=> 1<<30, 'm' => 1<<20, 'k' => 1<<10 ];
return intval($ini_v) * ($s[strtolower(substr($ini_v,-1))] ?: 1);
}
Looks like it isn't possible.
Because of this, I am going to continue using this code:
function convertBytes( $value ) {
if ( is_numeric( $value ) ) {
return $value;
} else {
$value_length = strlen($value);
$qty = substr( $value, 0, $value_length - 1 );
$unit = strtolower( substr( $value, $value_length - 1 ) );
switch ( $unit ) {
case 'k':
$qty *= 1024;
break;
case 'm':
$qty *= 1048576;
break;
case 'g':
$qty *= 1073741824;
break;
}
return $qty;
}
}
$maxFileSize = convertBytes(ini_get('upload_max_filesize'));
Originally from this helpful php.net comment.
STILL OPEN TO ACCEPT BETTER ANSWERS
I don't think so, at least not in the way you have defined it. There are so many other factors that come into consideration for maximum file upload size, most notably the connection speed of the user as well as the timeout setting for the web server as well as the PHP process(es).
A more useful metric for you might be to decide what is a reasonable maximum file size for the types of files you expect to receive for a given input. Make the decision on what is reasonable for your use case and set a policy around that.
Well you can always use this syntax, which will give you correct numbers from PHP ini file:
$maxUpload = (int)(ini_get('upload_max_filesize'));
$maxPost = (int)(ini_get('post_max_size'));
Mart
I am quite surprise to find the above-mentioned error in my error log because I thought I have already done the necessary work to catch the error in my PHP script:
if ($_FILES['image']['error'] == 0)
{
// go ahead to process the image file
}
else
{
// determine the error
switch($_FILES['image']['error'])
{
case "1":
$msg = "Uploaded file exceeds the upload_max_filesize directive in php.ini.";
break;
....
}
}
In my PHP.ini script, the relevant settings are:
memory_limit = 128M
post_max_size = 3M
upload_max_filesize = 500K
I understand that the 3M is equivalent to 3145728 bytes and that this is what that is triggering the error. If the file size is above 500k but less than 3M, the PHP script would be able to run as per normal, issuing the error message in $msg as per case 1.
How do I catch this error instead of letting the script terminate abruptly with a PHP warning when post size exceeds post_max_size but still well within the memory limit? I have looked at similar questions here, here and here, but couldn't find an answer.
Found an alternative solution that does not deal with the error directly. The following code is written by a software engineer Andrew Curioso in his blog:
if($_SERVER['REQUEST_METHOD'] == 'POST' && empty($_POST) &&
empty($_FILES) && $_SERVER['CONTENT_LENGTH'] > 0)
{
$displayMaxSize = ini_get('post_max_size');
switch(substr($displayMaxSize,-1))
{
case 'G':
$displayMaxSize = $displayMaxSize * 1024;
case 'M':
$displayMaxSize = $displayMaxSize * 1024;
case 'K':
$displayMaxSize = $displayMaxSize * 1024;
}
$error = 'Posted data is too large. '.
$_SERVER[CONTENT_LENGTH].
' bytes exceeds the maximum size of '.
$displayMaxSize.' bytes.';
}
As explained in his article, when the post size exceeds post_max_size, the super global arrays of $_POST and $_FILES will become empty. So, by testing for these and by confirming that there is some content being sent using the POST method, it can be deduced that such an error has occurred.
There is actually a similar question here, which I didn't manage to find earlier.
You could check it with javascript first before the upload even takes place?
// Assumed input for file in your HTML
<input type="file" id="myFile" />
//binds to onchange event of your input field
$('#myFile').bind('change', function() {
alert(this.files[0].size);
});
You can also pop a try catch around it:
try
{
if (!move_uploaded_file( 'blah blah' ))
{
throw new Exception('Too damn big.');
}
// Can do your other error checking here...
echo "Upload Complete!";
}
catch (Exception $e)
{
die ('File did not upload: ' . $e->getMessage());
}
I'm having issues uploading a pdf to my server. The upload_max_filesize is 2M and the file(s) are more then that, around 4M. I found a post with a similar issue to mine here
$_FILE upload large file gives error 1 even though upload_max_size is bigger than the file size
What I can gather from php.net for the correct usage of ini_set commands is this, which I am currently using.
ini_set('upload_max_filesize', 100000000);
ini_set('post_max_size', 110000000);
ini_set('memory_limit', 120000000);
ini_set('max_input_time', 20);
But in the link I posted it seems they are using a different method (if they aren't just summarizing the correct code that is). But It seems my code isn't working as is either. I have <?php phpinfo(); ?> at the bottom of my page and it says the upload_max_filesize is still 2M. Am I using the correct syntax for ini_set? or is my issue with upload my pdfs something else?
My code handling the upload is
//======================pdf upload=====================
if ($_POST['erasePDF'] == "Yes") //checking if erase box was checked and erasing if true
{
if (file_exists($pdf))
{
unlink( $pdf );
$pdf = "";
}
}
print_r($_FILES['pdf']);
if (!empty($_FILES['pdf']['name'])) //checking if file upload box contains a value
{
$saveDirectoryPDF = 'pdfs/'; //name of folder to upload to
$tempName = $_FILES['pdf']['tmp_name']; //getting the temp name on server
$pdf = $_FILES['pdf']['name']; //getting file name on users computer
$test = array();
$test = explode(".", $pdf);
if((count($test) > 2) || ($test[1] != "pdf" && $test[1] != "doc" && $test[1] != "docx")){
echo "invalid file";
}else{
$count = 1;
do{
$location = $saveDirectoryPDF . $count . $pdf;
$count++;
}while(is_file($location));
if (move_uploaded_file($tempName, $location)) //Moves the temp file on server
{ //to directory with real name
$pdf = $location;
}
else
{
echo "hi";
echo '<h1> There was an error while uploading the file.</h1>';
}
}
}else{
$pdf = "";
}
if(isset($_POST['link']) && $_POST['link'] != ""){
$pdf = $_POST['link'];
}
//======================end of pdf upload==============
The output of the line 'print_r($_FILES['pdf']);' is
Array ( [name] => takeoutmenu.pdf [type] => [tmp_name] => [error] => 1 [size] => 0 )
Some providers does not allow you change certain values in running time. Instead of this, try to either change it in the real php.ini file or use an .htaccess (For Apache web servers) where you can add your configuration. You can find more information in the PHP.net article about this subject: How to change configuration settings.
Based on your story, example .htaccess
<IfModule mod_php5.c>
php_value upload_max_filesize 100000000
php_value post_max_size 110000000
php_value memory_limit 120000000
php_value max_input_time 20
</IfModule>
hi guys i am uploading the images using the #PhP file upload Method # If i upload 10 Images at a time (Each Images is 2000 /3000 dimension). then the on click save function is not working. if i upload 5 images or less than five images then its working fine wats wrong with my coding i just include my php code with this post <input value="Save" type="submit" name="SubSave" id="SubSave" onClick="return changes();">
if($_POST['SubSave'] == "Save"){
$aid = $_GET['rid'];
$updcount = $_POST['theValue'];
if($_SESSION["almgtype"]==1 || (GetUserNoPhoto($_SESSION["almgid"]))>(GetTotalPhotoCount1($_SESSION["almgid"],$aid))) {
$uid = $_SESSION["almgid"];
for($k=1;$k<=$updcount;$k++) {
//echo $k;
echo $_FILES["uploadfile"]["type"];
if($_FILES["uploadfile".$k]["name"]!="") {
if(($_FILES["uploadfile".$k]["type"] == "image/gif") || ($_FILES["uploadfile".$k]["type"] == "image/jpeg")|| ($_FILES["uploadfile".$k]["type"] == "image/pjpeg") || ($_FILES["uploadfile".$k]["type"] == "image/png")) {
if ($_FILES["uploadfile".$k]["error"] > 0)
{
echo "Error: " . $_FILES["uploadfile".$k]["error"] . "<br />";
}
else
{
move_uploaded_file($_FILES["uploadfile".$k]["tmp_name"],
"photoalbum/" . $_FILES["uploadfile".$k]["name"]);
$uploadfile = "photoalbum/" . $_FILES["uploadfile".$k]["name"];
}
$path = $uploadfile;
$checklist = "select * from amt_photos1 where aid = '".trim($aid)."' and uid = '".trim($uid)."' and path = '".trim($path)."'";
$chkresult = mysql_query($checklist);
if(mysql_num_rows($chkresult) == 0) {
$i = 0;
$path =$uploadfile;
$result = "insert into amt_photos1 set uid = '".trim($uid)."',
aid = '".trim($aid)."',
path = '".trim($path)."',
status = '0',
createdby = '".$_SESSION["almgid"]."',
createddate = now()";
$rowlist = mysql_query($result) or die("Error:(".mysql_error().")".mysql_error());
}
/********************** if file already exist means ******************************************/
else {
$err= "The Uploaded file name ".$path." Is already exisit in the Album. Rename It or try to add Any other Photos";
}
/********************** if file already exist means ******************************************/
$path ="";
$uploadfile = "";
$i = "";
} // file extention
else {
$err= "Unable To Upload The File Please Check The File Extention.Try Again Later";
}
}
}
}
} // if save close
You probably need to change the maximum POST size in your php.ini configuration file (post_max_size setting).
You can use the command phpinfo() to dump your configuration. Likely, as others have stated you need to increase the upload size and execution time.
These can be modified through a .htaccess file.
php_value upload_max_filesize 20M
php_value post_max_size 20M
php_value max_execution_time 200
php_value max_input_time 200
Just as a warning: Your upload handling script will make it utterly trivial to completely subvert your server:
You blindly trust that the $_FILES[...]['type'] value is correctly set - this value is completely under the user's control, and they can stuff in "image/jpeg" and upload any type of file they want
You blindly trust that the $_FILES[...]['filename'] value is correctly set - again, this value is completely under the user's control, and they can stuff in "hackme.php" if they want to
You blindly write the file to your photoalbum directory, but don't check if the user-supplied filename contains pathing data
So, what happens if someone uploads the following file:
$_FILES['uploadfile0']['type'] = 'image/gif';
$_FILES['uploadfile0']['filename'] = '../pwn_me.php';
You've now happily put a user-provided PHP script ONTO YOUR WEBSERVER and they can now do anything they want.
On top of that, your database queries blindly insert the same data into the queries, leaving you wide open to SQL injection attacks. As well, you don't check for filename collisions until AFTER you've moved the file. So, someone could upload a malicious script, but only do it once for that particular filename. Congratulations, you've implemented versioned attacks on your server. You'll have "pwn_me.php", "pwn_me2.php", "pwn_me3.php", "my_little_pwnme.php", and so on.