PDA

View Full Version : basic file upload class with validation


met
09-04-2010, 05:03 PM
<?php
/**
* File Uploader Class
*
*/

class file_upload {

/**
*
* @var $error - contains an error message generated
* @var $allowed - array of allowed file extensions, passed to the constructor
*/
private $errors=array();
private $allowed=array();
private $file_ext;
private $file;
private $upload_path;
private $max_file_size;
private $message;
private $site_url;

/**
* The constructor, takes an array of allowed file extensions by default.
* If no array is supplied, defaults are used.
*
* @param upload_path - the location on the server for the upload folder.
* @param max_file_size - the max file size in bytes to be uploaded.
* @param array $allowed - An array of allowed file types
*/
function __construct($params)
{
$this->upload_path = ($params['upload_path'] != "" ? $params['upload_path'] : 'uploads/');
$this->max_file_size = ($params['max_file_size'] != "" ? $params['max_file_size'] : 1000000);
$this->allowed = ($params['allowed'] != "" ? $params['allowed'] : array('images/jpg','images/gif','images/jpeg','images/png'));
$this->site_url = 'http://www.' . $_SERVER["SERVER_NAME"] . '/';
}
/**
* This method is used to determine if a valid, writable path was supplied
* a trailing slash is appended if there was not one originally
* If the path doesn't exist, the system will attempt to create it.
*/
function valid_path()
{
$path = $this->upload_path;

/*
* If no path has been set, then just return false,
* no further processing is needed
*/
if($path=="")
{
$errors[] = 'No path is specified.';
$this->set_errors($errors);
return false;
}

/*
* Append a trailing slash if there was not one
*/

if(substr($path,-1) != '/')
{
$this->upload_path = $this->upload_path . '/';
}

if(!is_dir($path))
{
if(!mkdir($path))
{
$errors[] = 'The path is not a valid and the system could not create it. <br /> You supplied: <b>' . $path . '</b>.';
}
}

if(!is_writable($path))
{
$errors[] = 'The directory you have supplied is not writable. Pleae check the permissions.';
}

if(count($errors)>0)
{
$this->set_errors($errors);
return false;
}
else
{
return true;
}
}

/**
* Check the supplied file name for a valid extension.
*
* @param string $file - The name of the file being uploaded.
* @return bool true/false - Returns true on valid extension, else false.
*/
function check_file($file)
{
// Check if a file was provided, else return false.
if($file['userfile']['name']=="")
{
$errors[] = 'You have not selected a file.';
$this->set_errors($errors);
return false;
}

// See if the file type is in the allowed array. Return an error if the file isn't allowed
if(!in_array($file['userfile']['type'], $this->allowed))
{
$errors[] = 'This type of file is not allowed <b>' . $file['userfile']['type'] . '</b>';
}

// Check to see if the file is too large
if($file['userfile']['size'] > $this->max_file_size)
{
$errors[] = 'This file is too large to upload. Max size is <b>' . $this->max_file_size . ' bytes</b>.';
}

if(count($errors) > 0)
{
$this->set_errors($errors);
return false;
}
// It's a valid file...return true.
return true;
}

/*
* this method gets the extension of the file
* used when renaming the file at upload to ensure the file
* name is kept intact
*/
function get_ext($file_name)
{
if(!$file_name)
{
$errors[] = 'You have not selected a file.';
$this->set_errors($errors);
return false;
}
// this allows for .jpeg/.indd type files (with 4 letters in the extension)
// white space is trimmed
$this->file_ext=trim(substr($file_name,strrpos($file_name,'.')+1,4));

return $this->file_ext;
}

/**
* Upload function takes a file name as a parameter.
* If no file is supplied, return an error message.
*
* @param string $file - the FILE array
*/
function upload($file=NULL, $new_name="")
{
// check the file is the right type, size
if($this->check_file($file))
{

//if a new name was supplied, adjust the target path accordingly
if($new_name!="")
{
$target_path = $this->upload_path . $new_name . '.' . $this->get_ext($file['userfile']['name']);
}
else
{
// use the target upload directory and the default file name
$target_path = $this->upload_path . basename($file['userfile']['name']);
}

/*
* this doesn't appear to work at the moment, not sure why
*/
if(file_exists($this->site_url . $this->upload_path . $file['userfile']['name']) ||
file_exists($this->site_url . $this->upload_path . $new_name . '.' . $this->get_ext($file['userfile']['name'])))
{

$errors[] = 'A file with that name already exists, please choose another name.';
$this->set_errors($errors);
return false;
}

//here we upload the file
if(move_uploaded_file($file['userfile']['tmp_name'], $target_path))
{
$this->message='File has been uploaded.';
return true;
}
else
{
$errors[]='There has been a problem uploading the file: <br />' . $file['userfile']['error'];
$this->set_errors($errors);
}

}
// if we get here, then the upload wasn't successful.
// return false.
return false;
}

//method to set errors supplied as a 1 dimensional array.
function set_errors($errors)
{
if(count($errors)>0)
{
foreach($errors as $error)
{
$this->errors[] = $error;
}
}
}

// format any errors in a UL and return them
function show_errors()
{
if(count($this->errors)>0)
{
$message = '<p>There have been some errors:</p>';
$message .= '<ul class="errors">';
foreach($this->errors as $error)
{
$message .= '<li> ' . $error . ' </li>';
}
$message .= '</ul>';
return $message;
}

}

// the upload was successful, return the success message
function upload_success()
{
return $this->message;
}
}




Example Usage


<?php
include('file_upload_class.php');

$params['upload_path'] = 'uploads/';
$params['max_file_size'] = 1000000;
$params['allowed'] = array('image/jpg', 'image/gif', 'image/png', 'image/jpeg');

$upload = new file_upload($params);
if($upload->valid_path()==false)
{
$message = $upload->show_errors();
}
if($_POST['submit'])
{
$do_upload=$upload->upload($_FILES,$_POST['new_name']);
if($do_upload)
{
$message = '<p>' . $upload->upload_success() . '</p>';
}
else
{
$message = $upload->show_errors();
}
}

?>
<h1>OOP File Uploader</h1>
<?php echo $message; ?>
<form action="" method="post" enctype="multipart/form-data" name="uploader">
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
<p>Choose a File:</p>
<input name="userfile" type="file" />
<p>Enter a new name: (optional)</p>
<input name="new_name" value="" />
<p><input name="submit" type="submit" value="Upload" /></p>
</form>


Just getting in to OOP. Improvements welcomed

(very basic)~features include

basic parameter setting @ constructor
optional renaming of file upload
custom validation of accepted file type
max file size
custom file upload path via params