This question already has answers here:
$_POST data returns empty when headers are > POST_MAX_SIZE
(5 answers)
Closed 8 years ago.
I have a php upload file process that works quite well. However I wanted to add some validation to ensure large files weren't uploaded, however when I was testing I noticed some strange behaviour;
I set post_max_size & upload_max_filesize to 5M (restarted server) but found that if I uploaded a file larger than 5M the POST data was lost, so I couldn't do a check on $_FILES['uploadedFile']['size']
I kinda solved the issue by ensuring that the post_max_size & upload_max_filesize were set to 10M (assuming of course no one will be silly enough to try a file bigger than that - its really for text files so they shouldn't) After which I could do my size validation without issue;
if($_FILES['uploadedFile']['size'] < 3072000)
{
//do upload stuff
}
else
{
$errorMessage .= 'File size to big, exceeds 3M Limit.';
}
I assume the problem is that the POST is getting obliterated because it exceeded post_max_size??? I searched through a lot of pages but couldn't see anyone else having a problem with this so I'm not sure if my assumption is right. If I upload a file bigger than 10Mm I still get the problem.
You are correct. Uploaded data is ignored, when the size limit is exceeded. So, you don't get access to the ['size'] info.
Instead, you need to validate your upload like this:
<?php
if ($_FILES['uploadedFile']['error'] == UPLOAD_ERR_OK)
{
// success - move uploaded file and process stuff here
}
else
{
// error
switch ($_FILES['uploadedFile']['error'])
{
case UPLOAD_ERR_INI_SIZE:
echo "The uploaded file exceeds the upload_max_filesize directive in php.ini."; break;
case UPLOAD_ERR_FORM_SIZE:
echo "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form."; break;
case UPLOAD_ERR_PARTIAL:
echo "The uploaded file was only partially uploaded. "; break;
// etc... see the full list here http://uk1.php.net/manual/en/features.file-upload.errors.php
}
}
Related
I have an upload.php script, that I access from a mobile device, to upload documents to.
Whenever I upload an image of some sort, that is < 1MB, it works perfectly, however, when uploading a file larger than that, it will be corrupted.
The upload script also renames the file, and removes the extension from it, if this could have anything to do with the error...
Here's the script:
<?php header('Access-Control-Allow-Origin: *');
//Read parameters - I use this when I'm adding the file to the database.
$documentuniqueid = addslashes($_REQUEST['documentuniqueid']);
$type = addslashes($_REQUEST['type']);
$notes = addslashes($_REQUEST['notes']);
//Get file name
$filename = urldecode($_FILES["file"]["name"]);
// Check for errors
if($_FILES['file']['error'] > 0){
outputJSON('An error ocurred when uploading.');
}
// Check filetype
//if($_FILES['file']['type'] != 'image/png'){
// outputJSON('Unsupported filetype uploaded.');
//}
// Check filesize
if($_FILES['file']['size'] > 500000){
outputJSON('File uploaded exceeds maximum upload size.');
}
// Check if the file exists
if(file_exists('upload/' . $_FILES['file']['name'])){
outputJSON('File with that name already exists.');
}
// Upload file
if(!move_uploaded_file($_FILES['file']['tmp_name'], 'documents/'.$documentuniqueid)){
outputJSON('Error uploading file - check destination is writeable.');
}
?>
Download script looks like this:
<?php
sleep(2);
$document_id = addslashes($_REQUEST['document_id']);
if($document_id != "") {
$real_document_name = GetRealFileName($document_id);
if($real_document_name != "ERROR") {
$original_filename = "http://www.whatever.com/documents/".$document_id;
$new_filename = $real_document_name;
//Headers
$finfo = finfo_open(FILEINFO_MIME_TYPE);
header('Content-Type: '.finfo_file($finfo, $original_filename));
header("Content-Length: " . filesize($original_filename));
header('Content-disposition: attachment; filename="'.$new_filename.'"');
//clean up
ob_clean();
flush();
readfile($original_filename);
exit();
}
}
?>
Any tips on improving this?
Or any insight, on why is this not working correctly?
You can see that I am renaming the files upon upload, to a random string, and them when downloading, I look up the filenames and rename it back to the original one.
That works as expected for the small file sizes.
I also have to note, that even if I go in manually into the FTP, download the uploaded file and add the right extension myself, I'm unable to open them. The images look messed up, and PDFs, for instance are corrupted.
PHP DETAILS:
both post_max_size and upload_max_filesize is set to 100M. max_file_uploads is set to 20 and file_uploads is ON
max_input_time : 60
max_execution_time : 3000
Increase the size of upload file property of the php.ini file inside /etc/php5/apache2/.
Set:
upload_max_filesize = 50M
I think you do not have enough space in your host, Try to upload by FTP "FileZilla for example" and check the log messages
also do not forget to check these values
upload_max_filesize
post_max_size
max_input_time
max_execution_time
To keep the original name of file you need to change
move_uploaded_file($_FILES['file']['tmp_name'], 'documents/'.$documentuniqueid)
to
move_uploaded_file -
move_uploaded_file($_FILES['file']['tmp_name'], $_FILES['file']['name'])
or write this line in upload script to see the information about the file
$_FILES -
print_r($_FILES);
sorry for my english, i hope i helped.
I have a form that lets users upload files but I'm having problems detecting files that are too large.
I have the following set in php.ini:
upload_max_filesize = 10M
post_max_size = 20M
I understand that the standard way to detect if files are larger than the config file allows is to check $_FILES['file_name']['error']. However this only works for me if the actual file is greater than upload_max_filesize and smaller than post_max_size.
If the actual file size is greater than post_max_size then the $_FILES variable is removed and I get the log message:
PHP Warning: POST Content-Length of xxx bytes exceeds the limit of
yyy ...
So the question: How do I detect if a user is uploading a file that is greater than post_max_size? I need to display a valid user message if this happens.
Thanks.
I suggest you use set_error_handler() and check for E_USER_WARNING error + appropriate message, and then send it to a user, possibly via throwing an Exception, possibly some other way.
Like this:
$filesize = $_FILES['file']['size'];
$limit = ini_get('post_max_size');
if($filesize > $limit) {
trigger_error("POST Content-Length of $filesize bytes exceeds the limit of $limit bytes.", E_WARNING);
}
else {
// upload file
}
I have an Apache server where files are uploaded in an HTTP post request (<form enctype="multipart/form-data" action="upload.php" method="post">). It happens from time to time (very rarely, but it happens nonetheless), for reasons that still elude me, that after a file has been uploaded, its size on disk will not match the size of the original file.
What I'd like to do is to catch those errors before returning from the PHP script which copies the file from /tmp to its final destination. My first idea was to compare $_FILES['uploadedfile']['size'] and filesize($target_path), which seems to work fine for files up to 2GB. However, as soon as the file size's number of bytes is over 32 bits long, $_FILES['uploadedfile']['size'] overflows and becomes negative. Moreover, I suspect that using this value as the "reference file size" might be too late in the upload process (i.e. it's the file size on the server, not on the client).
There's the possibility of extracting the file size from $_SERVER['CONTENT_LENGTH'], but this value also includes what seems to be request "metadata", and I could not find documentation on how to separate that data from the actual file size (the "metadata" size changes from request to request)
The easiest way would be to ask the client to post the source's file size as a request parameter, but I'd like to have as little change as possible on the client's side.
I was also told an "HTTP PUT" could prevent the problem in the first place, but I'm still in the early stages of investigating that. I'd still like to find a solution with my current POST method.
For reference, my upload script looks approximately like this now:
$id = strtolower($_POST["assetid"]);
$project = strtolower($_POST["project"]);
$target_path = Settings::getAssetPath($project,$id);
if (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
if (filesize($target_path) != $_FILES['uploadedfile']['size']){
header("HTTP/1.0 500 Internal Server Error");
$result .= "Uploaded file size does not match source file size!<br />";
}
else {
header("HTTP/1.0 200 OK");
$result .= "The file " . basename($_FILES['uploadedfile']['name']) . " has been uploaded successfully.";
}
} else {
header("HTTP/1.0 500 Internal Server Error");
$result .= "There was an error uploading the file, please try again!<br />";
}
Any ideas are very welcome!
Your upload script is incorrect. ['size'] is what has been received by the server. If the upload aborts/fails for any reason, ['size'] WILL be incorrect. You must check for upload success before doing ANYTHING with the upload data:
if($_FILES['uploadedfile']['error'] !== UPLOAD_ERR_OK) {
die("Upload failed with error code " . $_FILES['uploadedfile']['error']);
}
the error codes are defined here: http://www.php.net/manual/en/features.file-upload.errors.php
To start off, I've set my post_max_size in /etc/php.ini to 4M just as a test. I have a check in place to check for file type and size of file. I want to only accept JPG, GIF and PNG. The file size cannot be larger than 4M. It seems that if the file size is larger than what's set in post_max_size, my code won't throw an error. If I set my PHP to deny uploads larger than let's say 2M but less than 4M, it'll throw an error (what i want). I believe this is due to PHP not accepting anything over 4M.
if (is_uploaded_file($_FILES["file"]["tmp_name"]))
{
$file_type = exif_imagetype($_FILES["file"]["tmp_name"]);
} else {
$this->form_validation->set_message('valid_image', 'Error uploading file!!!');
return false;
}
There is another ini flag upload_max_filesize that you should increase to your new limit as well
Use the value in $_FILES["file"]["error"] to check the upload status.
Not sure, but I would check for file size on the client before the upload happens. This approach would upload the whole file to the server first before giving the error even if it worked.
($_FILES['uploaded_file']['error'] == 0)
is a successful upload.
I have a file (image) upload script in PHP that I use to upload and resize images... It uses a simple MIME type and size validation so only jpg images are allowed and 1MB max file size.
I recently discovered a problem. When I try tu upload a .avi file using the script, the script processes the file like its the correct MIME type and size and then just do nothing, just takes me back to the upload form without any error message. (Instead of showing a "file too big" message).
I mean, if I try to upload a .gif or .txt or something else I get an error, as expected.
If I try to upload any file bigger than 1MB I get an error, as expected.
Only when I try to upload a .avi file with more than 1MB I dont get any kind of error.....
Well, here the first par of the code:
// define a constant for the maximum upload size
define ('MAX_FILE_SIZE', 1024000);
if (array_key_exists('upload', $_POST)) {
// define constant for upload folder
define('UPLOAD_DIR', 'C:/Wamp/www/Version-1.4/posters_uploaded/');
// replace any spaces in original filename with underscores. At the same time, assign to a simpler variable
$file = str_replace(' ', '_', $_FILES['image']['name']);
// convert the maximum size to KB
$max = number_format(MAX_FILE_SIZE/1024, 1).'kb';
// create an array of permitted MIME types
$permitted = array('image/jpeg','image/pjpeg');
// begin by assuming the file is unacceptable
$sizeOK = false;
$typeOK = false;
// check that file is within the permitted size
if ($_FILES['image']['size'] > 0 && $_FILES['image']['size'] <= MAX_FILE_SIZE) {
$sizeOK = true;
}
// check that file is of a permitted MIME type
foreach ($permitted as $type) {
if ($type == $_FILES['image']['type']) {
$typeOK = true;
break;
}
}
if ($sizeOK && $typeOK) {
switch($_FILES['image']['error']) {
case 0: // ...................
I'm just modifying a build PHP code so Im no expert...
Any suggestions??
Thanks.
http://us3.php.net/manual/en/features.file-upload.common-pitfalls.php
It looks like your upload_max_filesize ini-setting is too low. This would cause no error to be displayed when you upload a very large file such as an AVI video.
The reason you're seeing the errors with text files and .jpg images is likely because the size of those files are greater than 1 MB, but below your upload_max_filesize setting in php.ini.
Try echoing the value of ini_get("max_upload_filesize") and see what the value is if you don't have access to the php.ini file directly.
As john Rasch mentioned above, any file above the php.ini max_upload_filesize will not process at all. so you'll have no chance to test the error for you. you have to assume it was not uploaded and validate it if it was.
now that I understand your scenario better I think this is what you can do:
// at the top of your script
$upload_success = FALSE;
// when successfully detected upload
$upload_success = TRUE;
// if successful upload code is never run
$display_error = "File not uploaded, may be too large a file, "
. "please upload less than 1MB"
;
print $display_error;
main point being:
You can't always detect upload files that are too big because they get cut off at a level deeper than where the scripts run.
I'd also suggest that you don't believe the mime type. Sometimes people have .png or .gif file that have been renamed to .jpg, or they could upload incorrect files intentionally. Use getimagesize to check if these are valid jpeg images.
Don't forget, when uploading files, that there are actually two directives you need to pay attention to in php.ini. One is upload_max_filesize, but the other is post_max_size. Generally, post_max_size should at least be equal to, and probably greater than, upload_max_filesize. You can't upload a file greater than post_max_size, regardless of what you set your upload_max_filesize.
An AVI file won't match the mime types you have listed in your permitted array. After doing your $sizeOK and $typeOK checks, check to see what values they hold, and how your script handles those values. That might hold the key to the behavior of your script.
Above this line:
if ($_FILES['image']['size'] > 0 && $_FILES['image']['size'] <= MAX_FILE_SIZE) {
$sizeOK = true;
}
Put this:
echo '<pre>' . printr($_FILES) . </pre>;
That will show you what is inside the FILES array, and should make this pretty simple to debug. Try uploading the AVI with the above line added to your script.
Using $_FILES['image']['type'] for checking MIME is not reliable, it's base on header of the client and can be spoofed. Take a look at fileinfo extension to check MIME base on the real contents.
Eight years later, the short answer for anyone, like me, stumbling around for the answer to checking the image MIME type with PHP before uploading:
if (exif_imagetype($file['tmp_name']) != IMAGETYPE_JPEG) {
$file['error'] = 'Your picture must be jpg.';
}
From the manual: http://php.net/manual/en/function.exif-imagetype.php