You're here: Snippet Directory » PHP (128)
Language:

A fully featured upload class

Language: English
Programming Language: PHP
Published by: bealers [not registered]
Last Update: 5/15/2006
Views: 1774

Description

Upload.class.php, fully featured and supports multiple uploads. I'm in the process of Pearing this script, but it's fully functional as it stands

Code

1 <?php 2 /** 3 * Upload.class.php - File Upload Class v1.1 - 02 July 2001 4 * Copyright Darren Beale <mail@bealers.com> 5 * 6 * The contents of this file remain the intellectual property of Darren Beale. 7 * It is free for Personal and non-profit use as long as this 8 * entire comment block remains as-is. (Yes all of it) 9 * 10 * If you're using it commercially, please mail <mail@bealers.com> for a postal 11 * address. You can then get your boss to send me a measly 10 UKP so you can 12 * have unlimited use. 13 * 14 * Either way, If you modify or extend it, please Fw: me on a copy with a 15 * small note on what you've done and why. 16 * 17 * TODO: 18 * Check that source_dir is writeable 19 * Allow for auto-rename option on overwrite 20 * Handle exceptions and notices better 21 * Extend Pear/HTML/Form?? 22 * Fix Macintosh Upload issues (it won't work) 23 * 100% Pear Compliant 24 * PHPDoc commenting and bundled docs 25 * 26 * ChangeLog 27 * v1.0 - Initial Release 01/07/01 28 * v1.1 - Allowed for Multiple File uploads 02/07/01 29 * 30 * I WILL PROVIDE SUPPORT FOR THIS SCRIPT! 31 * This script *should* be able to handle the uploading of any file, if it 32 * doesn't as a first port of call please change the settings 33 * UPLOAD_DEBUG_OUTPUT and UPLOAD_ENV_OUTPUT to see what is happening. 34 * If you still have problems, mail 35 * me and I'll see what I can do. Don't expect me to code your app though! 36 * BTW You Need PHP > 4.0.2 37 * 38 * Useage: (bare bones) 39 * 40 <?php 41 require_once("Upload.class.php"); 42 43 $upload = new Upload(); 44 $upload->printFormStart("index.php"); 45 46 // put as many of these in as you want, 47 // pass a string filename, else a default is used. 48 $upload->printFormField(); 49 print"<br />"; 50 $upload->printFormField(); 51 52 $upload->printFormSubmit(); 53 $upload->printFormEnd(); 54 55 if ($submit) { 56 $upload->setAllowedMimeTypes(array("image/bmp","image/gif","image/pjpeg","image/jpeg","image/x-png")); 57 $upload->setUploadPath("c:\apache\htdocs"); 58 59 if ($upload->doUpload()) { 60 print "Files Uploaded!"; 61 } else { 62 $errors = $upload->getUploadErrors(); 63 print "<strong>::Errors occured::</strong><br />\n"; 64 while(list($filename,$values) = each($errors)) { 65 "File: " . print $filename . "<br />"; 66 $count = count($values); 67 for($i=0; $i<$count; $i++) { 68 print "==>" . $values[$i] . "<br />"; 69 } 70 } 71 } 72 } 73 ?> 74 * 75 * This class is complete re-write of my original code that I used 76 * as a basis for one of my PHPBuilder.com articles. 77 * http://www.phpbuilder.com/columns/bealers20000904.php3 78 * 79 * @author Darren Beale <mail@bealers.com> 80 */ 81 82 // CONSTANTS /////////////////////////////////////////////////////////////////// 83 84 /* 85 * Funny one this, during testing I couldn't assertain the dimensions of certain images. 86 * Until I can figure out why, you can set this flag to allow the images 87 * that don't return anything. 88 */ 89 if (!defined('UPLOAD_ALLOW_DUBIOUS_IMAGES')) { 90 define('UPLOAD_ALLOW_DUBIOUS_IMAGES', true); 91 } 92 93 /* 94 * Defaults only, they can be overridden using methods. 95 */ 96 if (!defined('UPLOAD_MAX_FILE_SIZE')) { 97 define('UPLOAD_MAX_FILE_SIZE', 1048576); // 1MB = 1048576 98 } 99 if (!defined('UPLOAD_IMAGE_MAX_WIDTH')) { 100 define('UPLOAD_IMAGE_MAX_WIDTH', 300); 101 } 102 if (!defined('UPLOAD_IMAGE_MAX_HEIGHT')) { 103 define('UPLOAD_IMAGE_MAX_HEIGHT', 300); 104 } 105 if (!defined('UPLOAD_FIELD_NAME')) { 106 define('UPLOAD_FIELD_NAME', "uploadFile"); 107 } 108 109 110 /* 111 * un-essential, only change if in development and you are having problems 112 */ 113 if (!defined('UPLOAD_DEBUG_OUTPUT')) { 114 define('UPLOAD_DEBUG_OUTPUT', false); 115 } 116 if (!defined('UPLOAD_ENV_OUTPUT')) { 117 define('UPLOAD_ENV_OUTPUT', false); 118 } 119 if (!defined('UPLOAD_LINE_BREAK')) { 120 define('UPLOAD_LINE_BREAK',"<br />"); // markup specific 121 } 122 123 class Upload 124 { 125 126 // {{{ properties 127 128 // array 129 var $uploadErrors; 130 var $registeredMimeTypes; 131 var $allowedMimeTypes; 132 133 // int 134 var $maxImageWidth; 135 var $maxImageHeight; 136 var $maxFileSize; 137 138 /* 139 * used to track the number of fields created and name them accordingly 140 */ 141 var $fieldCounter; 142 143 // string 144 var $uploadPath; 145 var $uploadFieldName; 146 var $fieldName; 147 var $errorType; 148 149 // bool 150 var $imageSizeOk; 151 var $uploadValidated; 152 var $uploadFail; 153 154 //}}} 155 //{{{ constructor 156 157 function Upload() 158 { 159 $this->uploadErrors = array(); 160 $this->registeredMimeTypes = array(); 161 $this->allowedMimeTypes = array(); 162 163 $this->maxImageWidth = 0; 164 $this->maxImageHeight = 0; 165 $this->maxFileSize = 0; 166 $this->fieldCounter = 0; 167 168 $this->uploadFieldName = ""; 169 $this->uploadPath = ""; 170 171 $this->imageSizeOk = false; 172 $this->uploadValidated = false; 173 $this->uploadFail = false; 174 175 /* 176 * set defaults 177 */ 178 if(!$this->registeredMimeTypes) { 179 $this->setRegisteredMimeTypes(); 180 } 181 182 if(!$this->maxImageWidth || !$this->maxImageHeight) { 183 $this->setMaxImageSize(); 184 } 185 186 if(!$this->maxFileSize) { 187 $this->setMaxFileSize(); 188 } 189 190 /* 191 * check to see what our environment is like, nothing happens unless 192 * UPLOAD_ENV_OUTPUT == true 193 */ 194 $this->checkLocalEnv(); 195 } 196 197 //}}} 198 199 /* 200 * public methods /////////////////////////////////////////////////////////// 201 */ 202 203 //{{{ setImageSize() 204 205 function setMaxImageSize($maxImageWidth = UPLOAD_IMAGE_MAX_WIDTH, $maxImageHeight = UPLOAD_IMAGE_MAX_HEIGHT) 206 { 207 $this->maxImageWidth = $maxImageWidth; 208 $this->maxImageHeight = $maxImageHeight; 209 } 210 211 //}}} 212 //{{{ setUploadPath() 213 214 function setUploadPath($uploadPath) 215 { 216 $this->uploadPath = $uploadPath; 217 } 218 219 //}}} 220 //{{{ setDestinationFileName() 221 222 function setDestinationFileName($destinationFileName = "uploadedFile.file") 223 { 224 $this->uploadFieldName = $destinationFileName; //+++ 225 } 226 227 //}}} 228 //{{{ setRegisteredMimeTypes() 229 230 function setRegisteredMimeTypes($registeredMimeTypes = array()) 231 { 232 if (sizeof($registeredMimeTypes) == 0) { 233 $this->registeredMimeTypes = 234 array( 235 "application/x-gzip-compressed" => ".tar.gz, .tgz", 236 "application/x-zip-compressed" => ".zip", 237 "application/x-tar" => ".tar", 238 "text/plain" => ".php, .txt, .inc (etc)", 239 "text/html" => ".html, .htm (etc)", 240 "image/bmp" => ".bmp, .ico", 241 "image/gif" => ".gif", 242 "image/pjpeg" => ".jpg, .jpeg", 243 "image/jpeg" => ".jpg, .jpeg", 244 "image/x-png" => ".png", 245 "audio/mpeg" => ".mp3 etc", 246 "audio/wav" => ".wav", 247 "application/pdf" => ".pdf", 248 "application/x-shockwave-flash" => ".swf", 249 "application/msword" => ".doc", 250 "application/vnd.ms-excel" => ".xls", 251 "application/octet-stream" => ".exe, .fla, .psd (etc)" 252 ); 253 } else { 254 $this->registeredMimeTypes = $registeredMimeTypes; 255 } 256 } 257 258 //}}} 259 //{{{ setAllowedMimeTypes() 260 261 function setAllowedMimeTypes($allowedMimeTypes = array()) 262 { 263 $this->allowedMimeTypes = $allowedMimeTypes; 264 } 265 266 //}}} 267 //{{{ setMaxFileSize() 268 269 function setMaxFileSize($maxFileSize = UPLOAD_MAX_FILE_SIZE) 270 { 271 $this->maxFileSize = $maxFileSize; 272 } 273 274 //}}} 275 //{{{ getUploadErrors() 276 277 function getUploadErrors() 278 { 279 return $this->uploadErrors; // array 280 } 281 282 //}}} 283 //{{{ printFormStart() TODO Extend HTML/Form ?? 284 285 function printFormStart($formAction = "./", $formMethod = "POST", $formName = "uploadForm", $formTarget = "_self", $formInlineJavaScript="") 286 { 287 print "<FORM ACTION='" . $formAction . 288 "' METHOD='" . $formMethod . 289 "' TARGET='" . $formTarget . 290 "' NAME='" . $formName . 291 "' ENCTYPE='multipart/form-data'" . $formInlineJavaScript . ">\n"; 292 } 293 294 //}}} 295 //{{{ printFormField() 296 297 function printFormField($fieldName = "") //+++ 298 { 299 if(!$fieldName) { 300 $fieldName = UPLOAD_FIELD_NAME . "_" . $this->fieldCounter; 301 } 302 print "<INPUT TYPE='FILE' NAME='" . $fieldName . "'>\n"; 303 print "<INPUT TYPE='HIDDEN' NAME='uploadFileName[" . 304 $this->fieldCounter . "]' VALUE='" . $fieldName . "'>\n"; 305 $this->fieldCounter++; 306 } 307 308 //}}} 309 //{{{ printFormSubmit() 310 311 function printFormSubmit($name="submit", $value="Upload", $formInlineJavaScript="") 312 { 313 print "<INPUT TYPE='HIDDEN' NAME='fieldCounter' VALUE='" . 314 $this->fieldCounter . "'>\n"; 315 print "<INPUT TYPE='SUBMIT' 316 NAME='" . $name . "' VALUE='" . $value . "'" . $formInlineJavaScript . ">\n"; 317 } 318 319 //}}} 320 //{{{ printFormEnd() 321 322 function printFormEnd() 323 { 324 print "</FORM>\n"; 325 } 326 327 //}}} 328 329 /* 330 * private methods ////////////////////////////////////////////////////////// 331 */ 332 333 //{{{ checkLocalEnv() 334 335 function checkLocalEnv() 336 { 337 /* 338 * this is a developer helper method and a pre-emptive strike 339 * towards any support emails ;) 340 */ 341 if (UPLOAD_ENV_OUTPUT) { 342 print UPLOAD_LINE_BREAK . "::PHP Environment - php.ini settings::" . UPLOAD_LINE_BREAK; 343 344 print UPLOAD_LINE_BREAK . "(php.ini variable: file_uploads)" . UPLOAD_LINE_BREAK; 345 print "HTTP File Uploads are "; 346 if (ini_get("file_uploads")) { 347 print "[ On ]"; 348 } else { 349 print "[ Off ] - This is a *major* issue. This script WILL NOT WORK!"; 350 print UPLOAD_LINE_BREAK . "Please check php.ini if you have access to it, if not you cannot use this Script, sorry."; 351 } 352 print UPLOAD_LINE_BREAK . UPLOAD_LINE_BREAK . "(php.ini variable: upload_tmp_dir)"; 353 print UPLOAD_LINE_BREAK . "Temp Upload Directory is set to [ " . ini_get("upload_tmp_dir") . " ]"; 354 print UPLOAD_LINE_BREAK . "Note, this is a fully qualified path on the *server*"; 355 356 print UPLOAD_LINE_BREAK . UPLOAD_LINE_BREAK . "(php.ini variable: upload_max_filesize)"; 357 print UPLOAD_LINE_BREAK . "Maximum allowed file size is set to [ " . ini_get("upload_max_filesize") . " ]"; 358 359 print UPLOAD_LINE_BREAK . UPLOAD_LINE_BREAK . "(php.ini variable: safe_mode)" . UPLOAD_LINE_BREAK; 360 print "Safe mode is "; 361 if (!ini_get("safe_mode")) { 362 print "[ Off ]"; 363 } else { 364 print "[ On ] - This script will almost certainly not work!"; 365 print UPLOAD_LINE_BREAK . "Please check php.ini if you have access to it, if not you cannot use this Script, sorry."; 366 } 367 } 368 } 369 370 //}}} 371 //{{{ setError() 372 373 function setError($errorType) 374 { 375 $this->uploadErrors[$this->HTTP_POST_FILES[$this->uploadFieldName]['name']][] = $errorType; //+++ 376 } 377 378 //}}} 379 //{{{ getAllowedMimeTypes() 380 381 function getAllowedMimeTypes() 382 { 383 return $this->allowedMimeTypes; 384 } 385 386 //}}} 387 //{{{ getUploadImageSize() 388 389 function getUploadImageSize() 390 { 391 $dimensions = GetImageSize($this->uploadFile); //+++ 392 393 /* 394 * I've been having some issues when uploading images with regards 395 * to the array passed back (i.e. No values) 396 */ 397 if (UPLOAD_DEBUG_OUTPUT) { 398 print "WIDTH: " . $dimensions[0] . UPLOAD_LINE_BREAK . "HEIGHT: " . 399 $dimensions[1] . UPLOAD_LINE_BREAK; 400 } 401 402 if (!UPLOAD_ALLOW_DUBIOUS_IMAGES) { 403 $this->setError("cannotGetImageSize"); 404 } 405 return array($dimensions[0],$dimensions[1]); 406 } 407 408 //}}} 409 //{{{ checkMimeType() 410 411 function checkMimeType() 412 { 413 if (!in_array($this->HTTP_POST_FILES[$this->uploadFieldName]['type'],$this->getAllowedMimeTypes())) { 414 $this->setError("mimeException"); 415 return false; 416 } else { 417 return true; 418 } 419 } 420 421 //}}} 422 //{{{ checkImageSize() 423 424 function checkImageSize() 425 { 426 $this->imageSize = $this->getUploadImageSize($this->uploadFile); //+++ 427 428 $imageSizeOK = true; 429 430 if ($this->imageSize[0] > $this->maxImageWidth) { 431 $imageSizeOK = false; 432 $this->setError("imageWidthException"); 433 } 434 435 if ($this->imageSize[1] > $this->maxImageHeight) { 436 $imageSizeOK= false; 437 $this->setError("imageHeightException"); 438 } 439 return $imageSizeOK; 440 } 441 442 //}}} 443 //{{{ copyFile() 444 445 function copyFile() // TODO check for is_writeable() 446 { 447 return move_uploaded_file($this->uploadFile, $this->uploadPath . "/" . $this->HTTP_POST_FILES[$this->uploadFieldName]['name']); //+++ 448 } 449 450 //}}} 451 //{{{ checkMaxFileSize() 452 453 function checkMaxFileSize() 454 { 455 if ($this->HTTP_POST_FILES[$this->uploadFieldName]['size'] > $this->maxFileSize) { //+++ ISSUE 456 return false; 457 } else { 458 return true; 459 } 460 } 461 462 //}}} 463 //{{{ setDefaults() 464 465 function setDefaults() 466 { 467 if(!$this->registeredMimeTypes) { 468 $this->setRegisteredMimeTypes(); 469 } 470 471 if(!$this->maxImageWidth || !$this->maxImageHeight) { 472 $this->setMaxImageSize(); 473 } 474 475 if(!$this->maxFileSize) { 476 $this->setMaxFileSize(); 477 } 478 } 479 480 //}}} 481 //{{{ processUpload() 482 483 function processUpload() { //+++ 484 485 /* 486 * Some MIME types seem to be rather randomly set, I'm assuming that this 487 * is an OS issue. For example M$ Word documents have been, in my experience, 488 * application/octet-stream, text/richtext or application/msword 489 * <shrug> if UPLOAD_DEBUG_OUTPUT == true, echo the MIME type. 490 * This is arguably useful for a development environment. 491 * Disabled by default. 492 */ 493 if (UPLOAD_DEBUG_OUTPUT) { 494 print UPLOAD_LINE_BREAK . "::DEBUG::" . UPLOAD_LINE_BREAK . 495 "Field Name: " . $this->uploadFieldName . 496 UPLOAD_LINE_BREAK . 497 "Mime Type: " . $this->HTTP_POST_FILES[$this->uploadFieldName]['type'] . 498 UPLOAD_LINE_BREAK . 499 "File Name: " . $this->HTTP_POST_FILES[$this->uploadFieldName]['name'] . 500 UPLOAD_LINE_BREAK . 501 "File Size: " . $this->HTTP_POST_FILES[$this->uploadFieldName]['size'] . 502 UPLOAD_LINE_BREAK . 503 "Temp Name: " . $this->HTTP_POST_FILES[$this->uploadFieldName]['tmp_name'] . 504 UPLOAD_LINE_BREAK; 505 } 506 507 $this->uploadFile = $this->HTTP_POST_FILES[$this->uploadFieldName]['tmp_name']; 508 $this->setDefaults(); 509 510 if (!$this->uploadPath) { 511 $this->setError("noUploadPathException"