File Upload Class, first time OOP
Posted: Thu Oct 08, 2009 7:19 am
First shot at a class, I needed a reusable file upload script.
Comments please, and on how I can make it more efficient.
EDIT: I did most of the changes proposed here plus I added fileInfo (although doesn't work on my server yet) mime type checking, a couple of functions to get the allowed extensions/mime types so to display them to the user, comma separated, added some extra error codes for http upload errors and also made it possible to upload to the folder using FTP through cURL.
There might be some cleanup work to do though this is much my completed class for now.
index.php (for testing)
file-uploader-class.php
Comments please, and on how I can make it more efficient.
EDIT: I did most of the changes proposed here plus I added fileInfo (although doesn't work on my server yet) mime type checking, a couple of functions to get the allowed extensions/mime types so to display them to the user, comma separated, added some extra error codes for http upload errors and also made it possible to upload to the folder using FTP through cURL.
There might be some cleanup work to do though this is much my completed class for now.
index.php (for testing)
Code: Select all
<?php
/* require the class file for the uploader */
require_once('file-uploader-class.php');
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>File Upload</title>
<style type="text/css">
body
{
font-family: Verdana, Georgia, Arial;
font-size:12px;
cursor:default;
}
</style>
</head>
<body>
<?php
/* create a new uploader object */
$uploader = new fileUploader(20000000, 0, 0, 2200, 2200, 0, array('.gif','.png','.jpg') , array('image/jpeg','image/jpg','image/png','image/gif'), 'uploads/images', 'http', '', '', '');
//(ftp method)
//$uploader = new fileUploader(20000000, 0, 0, 2200, 2200, 0, array('.gif','.png','.jpg') , array('image/jpeg','image/jpg','image/png','image/gif'), 'uploads/images', 'ftp', 'localhost/file-uploader-class', 'DEFAULT', '');
if (isset($_GET['action']) && strip_tags($_GET['action']) == 'upload')
{
/* upload from filename1 field */
$upload_message1 = $uploader->fileUpload('filename1','overwrite1');
/* upload from filename2 field */
$upload_message2 = $uploader->fileUpload('filename2','overwrite2');
/*output results*/
echo '<br />File 1 result:<strong>'.$upload_message1.'</strong><br />
<br />File 2 result:<strong>'.$upload_message2.'</strong><br />';
}
?>
<h3>File Upload</h3>
<form name="upload" style="width:400px;overflow:hidden;display:inline;" id="upload" enctype="multipart/form-data" method="post" action="index.php?action=upload">
<fieldset style="width:255px;">
<legend>UPLOAD</legend>
File:
<br />
<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $uploader->max_filesize; ?>" />
<input type="file" id="filename1" name="filename1" accept="<?php echo $uploader->listAllowedMimeTypes(); ?>" />
<br />
<label for="overwrite1"><input type="checkbox" id="overwrite1" name="overwrite1" value="1" /> overwrite if exists</label>
<br /><br />Allowed extensions: <?php echo $uploader->listAllowedExtensions(); ?><br /><br />
</fieldset>
<fieldset style="width:255px;">
<legend>UPLOAD</legend>
File:
<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $uploader->max_filesize; ?>" />
<br /><input type="file" id="filename2" name="filename2" accept="<?php echo $uploader->listAllowedMimeTypes(); ?>" />
<br />
<label for="overwrite2"><input type="checkbox" id="overwrite2" name="overwrite2" value="1" /> overwrite if exists</label>
<br /><br />Allowed extensions: <?php echo $uploader->listAllowedExtensions(); ?><br /><br />
</fieldset>
<br />
<input type="submit" name="upload" value="Upload" />
</form>
</body>
</html>
Code: Select all
<?php
/*
file-uploader-class.php
description: uploads a file in the specified directory
version: 2.0
last update: 22-Oct-2009
utilization URL: general
*/
class fileUploader
{
public $max_filesize = 20000000; //20 MegaBytes
public $max_file_width = 1000; //1000 pixels
public $max_file_height = 1000; //1000 pixels
public $min_file_width = 0; //0 pixels
public $min_file_height = 0; //0 pixels
public $filename_to_md5 = 0;
public $file_upload_dir = 'uploads'; //ftp needs full directory e.g. (site.com/ftp)
public $file_upload_path;
public $file_protocol = 'http'; //http or ftp
public $file_name = '';
public $file_name_original;
public $file_size;
public $file_width = 0;
public $file_height = 0;
public $file_extension = '';
public $file_temp_name = '';
public $file_name_tail;
public $file_error = 4;
public $file_overwrite = 0;
public $filesize_in_kbs;
public $file_field_name = 'filename';
public $file_overwrite_name = 'overwrite';
public $ftp_username = '';
public $ftp_password = '';
public $ftp_domain = '';
public $file_allowed_extensions = array();
public $file_allowed_mime_types = array();
private $file_upload_successful = 1;
private $UPLOAD_NO_FILE = 0;
private $UPLOAD_NO_FOLDER = 1;
private $UPLOAD_FILETYPE_INVALID = 2;
private $UPLOAD_MIMETYPE_INVALID = 3;
private $UPLOAD_FILENAME_EXISTS = 4;
private $UPLOAD_FILENAME_INVALID = 5;
private $UPLOAD_FILESIZE_LARGE = 6;
private $UPLOAD_FILEDIMENSIONS_LARGE = 7;
private $UPLOAD_FILEDIMENSIONS_SMALL = 8;
private $UPLOAD_FILESIZE_LARGE_INI = 9;
private $UPLOAD_FILESIZE_LARGE_FORM = 10;
private $UPLOAD_PARTIAL_ONLY = 11;
private $UPLOAD_NO_TEMPDIR = 12;
private $UPLOAD_NO_WRITE = 13;
private $UPLOAD_EXTENSION_STOP = 14;
private $UPLOAD_FILEINFO_ERROR = 15;
private $UPLOAD_CURL_ERROR = 16;
private $UPLOAD_ERROR = 17;
private $UPLOAD_SUCCESS = 18;
private $UPLOAD_SUCCESS_OVERWRITTEN = 19;
public function __construct( $max_filesize = false, $min_file_width = false, $min_file_height = false, $max_file_width = false, $max_file_height = false, $filename_to_md5 = false, $file_allowed_extensions = false, $file_allowed_mime_types = false, $file_upload_dir = false, $file_protocol = false, $ftp_domain = false, $ftp_username = false, $ftp_password = false)
{
$this->max_filesize = $max_filesize;
$this->max_file_width = $max_file_width;
$this->max_file_height = $max_file_height;
$this->min_file_width = $min_file_width;
$this->min_file_height = $min_file_height;
$this->filename_to_md5 = $filename_to_md5;
$this->file_allowed_extensions = $file_allowed_extensions;
$this->file_allowed_mime_types = $file_allowed_mime_types;
$this->file_upload_dir = $file_upload_dir.'/';
$this->file_protocol = $file_protocol;
$this->ftp_domain = $ftp_domain;
$this->ftp_username = $ftp_username;
$this->ftp_password = $ftp_password;
}
public function listAllowedExtensions()
{
$file_extensions = implode(',',$this->file_allowed_extensions);
return $file_extensions;
}
public function listAllowedMimeTypes()
{
$mime_types = implode(',',$this->file_allowed_mime_types);
return $mime_types;
}
public function fileUpload($file_field_name = false, $file_overwrite_name = false)
{
$this->file_field_name = $file_field_name;
$this->file_overwrite_name = $file_overwrite_name;
//post file name and other attributes from upload field
$this->file_name = strip_tags($_FILES[$this->file_field_name]['name']);
$this->file_temp_name = $_FILES[$this->file_field_name]['tmp_name'];
$this->file_size = $_FILES[$this->file_field_name]['size'];
$this->file_error = $_FILES[$this->file_field_name]['error'];
//small delay
//sleep(2);
//keep original filename
$this->file_name_original = $this->file_name;
//determine if an overwrite field has been assigned
if ($this->file_overwrite_name == '')
{
$this->file_overwrite = 0;
}
else
{
$this->file_overwrite = strip_tags($_POST[$this->file_overwrite_name]);
}
//filename to lowercase
$this->file_name = strtolower($this->file_name);
//get file extension only if the allowed extensions array is not empty
if (isset($this->file_allowed_extensions))
{
$this->file_extension = strtolower(substr($this->file_name,strrpos($this->file_name,".")));
}
//filename to md5
if ($this->filename_to_md5 == 1)
{
$this->file_name_tail = mt_rand(0,10000);
$this->file_name = md5($this->file_name).$this->file_name_tail.$this->file_extension;
}
//determine final upload path
if ($this->file_protocol=='http')
{
$this->file_upload_path = $this->file_upload_dir.$this->file_name;
}
else
{
$this->file_upload_original_path = $this->file_upload_dir.$this->file_name; //keep original for finfo
$this->file_upload_path = $this->ftp_domain.'/'.$this->file_upload_dir.$this->file_name_original;
}
//calculate filesize in kbs
$this->filesize_in_kbs = $this->file_size/1000;
/* file checks */
//initialize successful variable
$this->file_upload_successful = 1;
//no file selected
if ($this->file_name_original == '' || $this->file_name_original == null || empty($this->file_name_original) && $this->file_upload_successful == 1)
{
$this->file_upload_successful = 0;
return $this->UPLOAD_NO_FILE;
}
//no folder present
if ($this->file_protocol=='http' && $this->file_upload_successful == 1)
{
if (!is_dir($this->file_upload_dir))
{
$this->file_upload_successful = 0;
return $this->UPLOAD_NO_FOLDER;
}
}
//file type check
if (isset($this->file_allowed_extensions))
{
if (!in_array($this->file_extension, $this->file_allowed_extensions) && $this->file_upload_successful == 1)
{
$this->file_upload_successful = 0;
return $this->UPLOAD_FILETYPE_INVALID;
}
}
//check if file exists
if (file_exists($this->file_upload_dir.$this->file_name) && $this->file_upload_successful == 1 && !$this->file_overwrite == 1)
{
$this->file_upload_successful = 0;
return $this->UPLOAD_FILENAME_EXISTS;
}
//check filename validity
if ( $this->filename_to_md5 == 1)
{}
else
{
if ((preg_match("/^([a-z0-9]+[\040_\-]?)*\.[a-z]{3}$/i",basename($this->file_name))) && $this->file_upload_successful == 1)
{}
else
{
$this->file_upload_successful = 0;
return $this->UPLOAD_FILENAME_INVALID;
}
}
//file size check
if( $this->file_size > $this->max_filesize && $this->file_upload_successful == 1)
{
$this->file_upload_successful = 0;
return $this->UPLOAD_FILESIZE_LARGE;
}
//max file dimensions check
list($this->file_width, $this->file_height) = getimagesize($this->file_temp_name);
if(($this->file_width > $this->max_file_width || $this->file_height > $this->max_file_height) && $this->file_upload_successful == 1)
{
$this->file_upload_successful = 0;
return $this->UPLOAD_FILEDIMENSIONS_LARGE;
}
//min file dimensions check
if(($this->file_width < $this->min_file_width || $this->file_height < $this->min_file_height) && $this->file_upload_successful == 1)
{
$this->file_upload_successful = 0;
return $this->UPLOAD_FILEDIMENSIONS_SMALL;
}
if ($this->file_upload_successful == 1 )
{
// FTP UPLOAD //
if ($this->file_protocol == 'ftp')
{
//upload via FTP through curl
if (function_exists(curl_init))
{
$curl_handle = curl_init();
$fopen_handle = fopen($this->file_temp_name, 'r');
curl_setopt($curl_handle, CURLOPT_URL, 'ftp://'.$this->ftp_username.':'.$this->ftp_password.'@'.$this->file_upload_path);
curl_setopt($curl_handle, CURLOPT_UPLOAD, 1);
curl_setopt($curl_handle, CURLOPT_INFILE, $fopen_handle);
curl_setopt($curl_handle, CURLOPT_INFILESIZE, filesize($this->file_temp_name));
curl_exec ($curl_handle);
$ftp_error = curl_errno($curl_handle);
curl_close($curl_handle);
fclose($fopen_handle);
if ($ftp_error == 0)
{
//check real filetype by using fileInfo
if (function_exists(finfo_open) && isset($this->file_allowed_mime_types))
{
//start fileinfo connection
$finfo = finfo_open(FILEINFO_MIME);
if (!$finfo)
{
//there was an error with fileInfo still delete the file uploaded because it could be harmful
//unlink($this->file_upload_path);
return $this->UPLOAD_FILEINFO_ERROR;
}
//get real absolute path to check the file
$absupdir = realpath($this->file_upload_dir);
$get_mimetype = finfo_file($finfo, $absupdir.'/'.$this->file_name);
$get_mimetype = explode(';', $get_mimetype);
//close fileinfo connection
finfo_close($finfo);
if (!in_array($get_mimetype[0], $this->file_allowed_mime_types))
{
//suspicious file, delete it from server
unlink($absupdir.'/'.$this->file_name);
return $this->UPLOAD_MIMETYPE_INVALID;
}
}
if ($this->file_overwrite == 1)
{
return $this->UPLOAD_SUCCESS_OVERWRITTEN;
}
else
{
return $this->UPLOAD_SUCCESS;
}
}
else
{
return $this->UPLOAD_ERROR;
}
}
else
{
return $this->UPLOAD_CURL_ERROR;
}
}
else
{
// HTTP UPLOAD //
//move the file to the upload folder
if (move_uploaded_file($this->file_temp_name, $this->file_upload_path) && $this->file_error == 0)
{
//check real filetype by using fileInfo
if (function_exists(finfo_open) && isset($this->file_allowed_mime_types))
{
//start fileinfo connection
$finfo = finfo_open(FILEINFO_MIME);
if (!$finfo)
{
//there was an error with fileInfo still delete the file uploaded because it could be harmful
//unlink($this->file_upload_path);
return $this->UPLOAD_FILEINFO_ERROR;
}
//get real absolute path to check the file
$absupdir = realpath($this->file_upload_dir);
$get_mimetype = finfo_file($finfo, $absupdir.'/'.$this->file_name);
$get_mimetype = explode(';', $get_mimetype);
//close fileinfo connection
finfo_close($finfo);
if (!in_array($get_mimetype[0], $this->file_allowed_mime_types))
{
//suspicious file, delete it from server
unlink($this->file_upload_path);
return $this->UPLOAD_MIMETYPE_INVALID;
}
}
if ($this->file_overwrite == 1)
{
return $this->UPLOAD_SUCCESS_OVERWRITTEN;
}
else
{
return $this->UPLOAD_SUCCESS;
}
}
else
{
//return file upload error
switch($this->file_error)
{
case 1:
return $this->UPLOAD_FILESIZE_LARGE_INI;
case 2:
return $this->UPLOAD_FILESIZE_LARGE_FORM;
break;
case 3:
return $this->UPLOAD_PARTIAL_ONLY;
break;
case 4:
return $this->UPLOAD_NO_FILE;
break;
case 5:
return $this->UPLOAD_NO_TEMPDIR;
break;
case 6:
return $this->UPLOAD_NO_WRITE;
break;
case 7:
return $this->UPLOAD_EXTENSION_STOP;
break;
default:
return $this->UPLOAD_ERROR;
}
}
}
}
else
{
return $this->UPLOAD_ERROR;
}
}
}
?>