Upload Class

The upload class allows to securely process files that have been uploaded to the application. It allows you to filter uploads in various ways, define what the destination filenames should look like, or filter on size or length of the filename.

Uploaded files array

Information of every uploaded file is stored in a multidimensional array within the Upload class. For every file, an array is defined with the following fields:

Key Type Description
field string Name of the form field that was used to upload the file. If the form field was a (multidimensional) array, the array keys will be added to the fieldname separated by colons. So a field called "field[a][b][]" will be stored as "field:a:b:0".
name string Name of the file uploaded.
type string Mime-type of the file uploaded, as defined by the browser.
mimetype string Mime-type of the file uploaded, as determined by the Upload class. Note that this requires an up-to-date 'mime magic' file to be installed. This file is present on every *nix platform, but on Windows platforms, you might have to install this file yourself. If the mime-type can not be determined, this field contains the same value as 'type'.
file string The fully qualified filename of the temporary location of the uploaded file.
filename string The filename (basename) of the file uploaded.
extension string The extension of the file uploaded.
size integer The size in bytes of the file uploaded.
error boolean If true, the upload has failed, and the errors array contains why.
errors array An array of arrays, each with two values. 'error', containing the error code, and 'message', containing the error text.

Note that mime-type will always contain the most specific type. So if the browser claims it's an MS-Word document, but the mime-type is determined as being "application/octet-stream", the browser's mime-type is used, even if this may be wrong or unexpected! For example, a Microsoft .xlsx file might be detected as being "application/zip".

After you have called the save() method, this array structure is expanded with two extra fields, giving you information about what was actually saved.

Key Type Description
saved_to string Fully qualified path where the uploaded file was saved.
saved_as string Name of the file that was saved
errors array The errors array (and the error boolean) will be updated after calling save() to indicate any errors encountered when trying to save the file.

Defined error constants

The Upload class defines the following error constants:

Name Description
UPLOAD_ERR_OK There is no error, the file uploaded with success.
UPLOAD_ERR_INI_SIZE The uploaded file exceeds the upload_max_filesize directive in php.ini.
UPLOAD_ERR_FORM_SIZE The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.
UPLOAD_ERR_PARTIAL The uploaded file was only partially uploaded.
UPLOAD_ERR_NO_FILE No file was uploaded. Note that entries with this error will be filtered when the uploaded file list is processed.
UPLOAD_ERR_NO_TMP_DIR Missing a temporary folder.
UPLOAD_ERR_CANT_WRITE Failed to write file to disk.
UPLOAD_ERR_EXTENSION A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help.
UPLOAD_ERR_MAX_SIZE The file uploaded exceeds the maximum file size defined in the configuration.
UPLOAD_ERR_EXT_BLACKLISTED The extension of the file uploaded is defined in the extension blacklist.
UPLOAD_ERR_EXT_NOT_WHITELISTED The extension of the file uploaded is not defined in the extension whitelist.
UPLOAD_ERR_TYPE_BLACKLISTED The extension of the file uploaded is defined in the type blacklist.
UPLOAD_ERR_TYPE_NOT_WHITELISTED The extension of the file uploaded is not defined in the type whitelist.
UPLOAD_ERR_MIME_BLACKLISTED The extension of the file uploaded is defined in the mime-type blacklist.
UPLOAD_ERR_MIME_NOT_WHITELISTED The extension of the file uploaded is not defined in the mime-type whitelist.
UPLOAD_ERR_MAX_FILENAME_LENGTH The uploaded filename exceeds the defined maximum filename length.
UPLOAD_ERR_MOVE_FAILED The uploaded filename could not be moved from temporary storage to the path specified. This could mean that there's a permission issue.
UPLOAD_ERR_DUPLICATE_FILE The uploaded filename could not be saved because a file with that name already exists.

Note that to be able to upload files, your HTML <form> tag MUST contain enctype="multipart/form-data", and your form MUST contain at least one input field of type "file". Without it, all uploads will fail, and Upload::process will throw an exception!

Usage example

// Custom configuration for this upload
$config = array(
	'path' => DOCROOT.'files',
	'randomize' => true,
	'ext_whitelist' => array('img', 'jpg', 'jpeg', 'gif', 'png'),
);

// process the uploaded files in $_FILES
Upload::process($config);

// if there are any valid files
if (Upload::is_valid())
{
	// save them according to the config
	Upload::save();

	// call a model method to update the database
	Model_Uploads::add(Upload::get_files());
}

// and process any errors
foreach (Upload::get_errors() as $file)
{
	// $file is an array with all file information,
	// $file['errors'] contains an array of all error occurred
	// each array element is an an array containing 'error' and 'message'
}

is_valid()

The is_valid method can be used to check if there are any uploaded files present that have passed the upload validation.

Static Yes
Parameters None
Returns boolean - true if validated files exist, false if not.
Example
// do we have any uploaded files to save?
if (Upload::is_valid())
{
	Upload::save();
}

get_files($index = null)

The get_files method returns a multi-dimensional array with all files uploaded that have an error value of false.

Static Yes
Parameters
Param Default Description
$index optional index number of the file in the uploaded files array, or the name of a form field. If not specified, an array with all validated files is returned. If the index number is invalid, or if the index refers to a file with an error status of true, an exception is thrown.
Returns array
Example
// get the list of successfully uploaded files
foreach(Upload::get_files() as $file)
{
	// do something with the file info
}

// get the first uploaded file by index
if ( ! Upload::get_files(0))
{
	// first uploaded file was not succesfully uploaded
}

get_errors($index = null)

The get_errors method returns a multi-dimensional array with all files uploaded that have an error status of true.

Static Yes
Parameters
Param Default Description
$index optional index number of the file in the uploaded files array or the name of a form field. If not specified, an array with all invalid files is returned. If the index number is invalid, or if the index refers to a file with an error status of false, an exception is thrown.
Returns array
Example
// get the list of uploaded files with errors
foreach(Upload::get_errors() as $file)
{
	// do something with the file info
}

// get the first uploaded file by field name
if (Upload::get_errors('new_image'))
{
	// there was an error uploading the file for the form field 'new_image'
	// defined as <input type="file" name="new_image" />
}

Note that all upload fields in your form are submitted, even if they are optional. For fields that are left empty, the uploaded files array will have an empty file entry, with an error code of Upload::UPLOAD_ERR_NO_FILE. When processing errors, check the error code first, before trying to use any of the other fields in the returned array.

register($event, $callback)

The register method allows you to register callbacks for specific upload events, and allow you to add your own code to the process() and save() methods.

Static Yes
Parameters
Param Default Description
$event required name of the callback event you want to register. Valid names are 'validate', 'before' and 'after'.
$callback required Valid PHP callback function. This can be a function, a dynamic or static method, or a closure.
Returns boolean - true if the callback was registered, false if the registration failed.
Example
// register a before callback using a closure
Upload::register('before', function (&$file) {
	if ($file['error'] == Upload::UPLOAD_ERR_OK)
	{
		switch($file['extension'])
		{
			case "jpg":
			case "png":
			case "gif":
				// store these in the images subdirectory
				$file['file'] .= 'images/';
			break;

			case "css":
				// store these in the css subdirectory
				$file['file'] .= 'css/';
			break;

			case "js":
				// store these in the javascript subdirectory
				$file['file'] .= 'js/';
			break;

			default:
				// don't modify the path for all others
		}
	}
});

If you want to use a 'validate' callback, be sure to register it before you call Upload::process(). If you have used the 'auto_process' configuration setting, Upload::process() will be called as soon as you use the Upload class, which means you can't use this setting if you want to define callbacks at runtime.

The callback will receive a FuelPHP\Upload\File object as parameter. The entry is passed by reference, which allows the callback function to modify the entries of the array. You can access it as an array for backward compatibility reasons, but if migrate your application a version < 1.6 to 1.6+, check the value passed to your callbacks, as not all attributes are named the same as in pre-1.6.
If the callback function returns an integer, it is assumed to be an update of the uploaded file's error code. All other return values are ignored.

Note: if you alter the contents of the $file array in your callback, you have to make sure that the information is still valid, as the Upload class won't perform its checks again. The only exception to this rule is the 'file' path, which will be checked and created if required after the callback has been executed.

process($config = array())

The process method processes the information about all uploaded files, normalizes the different permutations of form field names that can be used, fetches additional information about the file and its mimetype, and validates the file.

Static Yes
Parameters
Param Default Description
$config optional array of configuration items, so you can override the settings defined in the configuration file.
Returns void
Throws FuelException, when no file upload attempt could be detected (i.e. form without "Enctype" or input field of type="file")
Example
// process the uploaded files
// set the max size to 10Kb, and allow overwrites of duplicate files
Upload::process(array(
	'max_size'    => 10240,
	'auto_rename' => false,
	'overwrite'   => true
));

If you intend to use this method, disable auto_process in the config, to avoid processing the uploaded files twice!

save( ... )

The save method saves all validated files uploaded to the path specified.

Static Yes
Parameters
Param Default Description
$integer optional Key of the files array returned by get_files(). This allows you to save an individual file from a set of uploaded files.
$array optional Array of keys of the files array returned by get_files(). This allows you to save a selection of files from a set of uploaded files.
$string optional The path the files should be saved to. This overrides the path specified in the configuration, or passed in the $config array when the process() method was called.

Note that the order in which these parameters are given is not relevant, and all of them are optional. But either use $integer or $array, and not both. If you do, the last one specified will be used.
Returns void
Example
// save all validated files
Upload::save();

// save only the first uploaded file
Upload::save(0);

// save the first, second and fourth uploaded file
Upload::save(0, 1, 3);

// save all validated files, and to an alternate location
$arr = Upload::get_files();
Upload::save(DOCROOT.'assets', array_keys($arr));

// process any errors on these files
foreach (Upload::get_errors() as $key => $file)
{
	// process the errors here
}