Skip to content

Instantly share code, notes, and snippets.

@zacscott
Last active December 29, 2015 10:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zacscott/7655076 to your computer and use it in GitHub Desktop.
Save zacscott/7655076 to your computer and use it in GitHub Desktop.
Utility to handle file uploads.
<?php
namespace \net\zeddev\util;
/** An error while uploading. */
class UploaderException extends \Exception { }
/** An invalid type for uploaded file. */
class UploaderTypeException extends UploaderException { }
/** An oversize uploaded file. */
class UploaderSizeException extends UploaderException { }
/**
* Utility to handle file uploads. Can be used like so:
*
* $uploader = new Uploader();
* $uploader->upload('formNameOfFile', 'path/to/store');
*
* **NOTE:** This file is released as a stand-alone utility. The original
* file and the associated unit test can be found on GitHub Gist -
* [here](https://gist.github.com/zscott92/7655076).
*
* @author Zachary Scott <zscott.dev@gmail.com>
*/
class Uploader {
public $imageMimes;
public $pdfMimes;
/** The name of the uploaded file. */
public $name;
/** The size of the uploaded file. */
public $size;
/** The mime type of the uploaded file. */
public $type;
/** The location of the uploaded file. */
public $path;
public function __construct() {
// valid mime types for images
$this->imageMimes = array(
"image/gif",
"image/jpeg",
"image/jpg",
"image/pjpeg",
"image/x-png",
"image/png"
);
// valid mime type for PDF files
$this->pdfMimes = array(
"application/pdf",
"application/x-pdf"
);
}
// returns english error message for file error code
private function uploadError($code) {
assert($code != null && is_int($code));
switch ($code) {
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
return "File is too large to upload!";
case UPLOAD_ERR_PARTIAL:
return "File upload was interrupted!";
case UPLOAD_ERR_NO_FILE:
return "No file was uploaded, please try again.";
case UPLOAD_ERR_NO_TMP_DIR:
case UPLOAD_ERR_CANT_WRITE:
case UPLOAD_ERR_EXTENSION:
return "File upload failed due to an internal error, please try again later.";
default:
return "Unknown file error!";
}
}
/**
* Handles checking and moving an uploaded file.
*
* @param $name The form name of the uploaded file.
* @param $dir The directory in which to place the file.
* @param $size The maximum size of the uploaded file. `null` for no limit.
* @param $mimes The valid mime types to accept. `null` for none.
*/
public function upload($name, $dir, $overwrite = false, $size = null, $mimes = null) {
// check exists
if (!isset($_FILES[$name]))
throw new UploaderException("No file was uploaded, please try again");
// check for upload error
if ($_FILES[$name]["error"] > 0) {
throw new UploaderException(
$this->uploadError($_FILES[$name]["error"])
);
}
// check the size of the file
if ($size != null) {
if ($_FILES[$name]['size'] > $size)
throw new UploaderSizeException($_FILES[$name]['size']);
}
// check mime type of uploaded file
if ($mimes != null) {
$type = $_FILES[$name]['type'];
if (!in_array($type, $mimes))
throw new UploaderTypeException($type);
}
$file = $_FILES[$name]['name'];
$filePath = $dir.'/'.$_FILES[$name]['name'];
// check file does not already exist
if (!$overwrite && file_exists($filePath))
throw new UploaderException("File $file already exists.");
// relocate
move_uploaded_file(
$_FILES[$name]['tmp_name'],
$filePath
);
// set file info
$this->name = $_FILES[$name]['name'];
$this->size = $_FILES[$name]['size'];
$this->type = $_FILES[$name]['type'];
$this->path = $filePath;
}
}
?>
<?php
// NOTE requires class.ErrorList.php vvvv
require_once dirname(__FILE__).'/code/class.ErrorList.php';
require_once dirname(__FILE__).'/code/class.Uploader.php';
$err = new ErrorList();
$uploader = new Uploader();
// handle form
if (isset($_POST['form'])) {
try {
// handle file upload
$uploader->upload(
'file',
'upload',
isset($_POST['overwrite']),
204800, // 200KB limit
$uploader->imageMimes
);
// upload successful at this point
$msg = "File uploaded successfully.";
} catch (UploaderTypeException $ex) {
$err->err("File must be an image");
} catch (UploaderSizeException $ex) {
$err->err("File must be 100KB or less");
} catch (UploaderException $ex) {
$err->err($ex->getMessage());
}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Uploader Test</title>
<style type="text/css">
.error {
color: red;
}
.msg {
color: green;
}
</style>
</head>
<body>
<h1>Uploader Test</h1>
<?php
// report any errors
echo $err->geterr();
// display message
if (isset($msg))
echo "<p class='msg'>$msg</p>";
// output uploaded file info
if (isset($_POST['form'])) {
echo "<p class='msg'>";
echo "Name: ". $uploader->name ."<br />";
echo "Size: ". sprintf('%.2f KiB', $uploader->size / 1024) ."<br />";
echo "Type: ". $uploader->type ."<br />";
echo "Path: ". $uploader->path ."<br />";
echo "</p>\n";
}
?>
<form action="upload.php"
method="post"
enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="checkbox" name="overwrite" value="1"/>Overwrite?<br />
<input type="submit" name="form" value="Upload"/>
</form>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment