UploadedFile.php 7.51 KB
Newer Older
1 2 3 4 5 6 7 8 9
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace yii\web;

10
use yii\widgets\Html;
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

/**
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class UploadedFile extends \yii\base\Object
{
	private static $_files;
	private $_name;
	private $_tempName;
	private $_type;
	private $_size;
	private $_error;


	/**
	 * Constructor.
	 * Instead of using the constructor to create a new instance,
	 * you should normally call [[getInstance()]] or [[getInstances()]]
	 * to obtain new instances.
	 * @param string $name the original name of the file being uploaded
	 * @param string $tempName the path of the uploaded file on the server.
	 * @param string $type the MIME-type of the uploaded file (such as "image/gif").
	 * @param integer $size the actual size of the uploaded file in bytes
	 * @param integer $error the error code
	 */
	public function __construct($name, $tempName, $type, $size, $error)
	{
		$this->_name = $name;
		$this->_tempName = $tempName;
		$this->_type = $type;
		$this->_size = $size;
		$this->_error = $error;
	}

	/**
	 * String output.
	 * This is PHP magic method that returns string representation of an object.
	 * The implementation here returns the uploaded file's name.
	 * @return string the string representation of the object
	 */
	public function __toString()
	{
		return $this->_name;
	}

	/**
	 * Returns an uploaded file for the given model attribute.
	 * The file should be uploaded using [[ActiveForm::fileInput()]].
	 * @param \yii\base\Model $model the data model
	 * @param string $attribute the attribute name. The attribute name may contain array indexes.
	 * For example, '[1]file' for tabular file uploading; and 'file[1]' for an element in a file array.
	 * @return UploadedFile the instance of the uploaded file.
	 * Null is returned if no file is uploaded for the specified model attribute.
	 * @see getInstanceByName
	 */
	public static function getInstance($model, $attribute)
	{
69
		$name = Html::getInputName($model, $attribute);
70 71 72 73 74 75 76 77 78 79 80 81 82
		return static::getInstanceByName($name);
	}

	/**
	 * Returns all uploaded files for the given model attribute.
	 * @param \yii\base\Model $model the data model
	 * @param string $attribute the attribute name. The attribute name may contain array indexes
	 * for tabular file uploading, e.g. '[1]file'.
	 * @return UploadedFile[] array of UploadedFile objects.
	 * Empty array is returned if no available file was found for the given attribute.
	 */
	public static function getInstances($model, $attribute)
	{
83
		$name = Html::getInputName($model, $attribute);
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
		return static::getInstancesByName($name);
	}

	/**
	 * Returns an uploaded file according to the given file input name.
	 * The name can be a plain string or a string like an array element (e.g. 'Post[imageFile]', or 'Post[0][imageFile]').
	 * @param string $name the name of the file input field.
	 * @return UploadedFile the instance of the uploaded file.
	 * Null is returned if no file is uploaded for the specified name.
	 */
	public static function getInstanceByName($name)
	{
		$files = static::loadFiles();
		return isset($files[$name]) ? $files[$name] : null;
	}

	/**
	 * Returns an array of uploaded files corresponding to the specified file input name.
	 * This is mainly used when multiple files were uploaded and saved as 'files[0]', 'files[1]',
	 * 'files[n]'..., and you can retrieve them all by passing 'files' as the name.
	 * @param string $name the name of the array of files
	 * @return UploadedFile[] the array of CUploadedFile objects. Empty array is returned
	 * if no adequate upload was found. Please note that this array will contain
	 * all files from all sub-arrays regardless how deeply nested they are.
	 */
	public static function getInstancesByName($name)
	{
		$files = static::loadFiles();
		if (isset($files[$name])) {
			return array($files[$name]);
		}
		$results = array();
		foreach ($files as $key => $file) {
			if (strpos($key, "{$name}[") === 0) {
				$results[] = self::$_files[$key];
			}
		}
		return $results;
	}

	/**
	 * Cleans up the loaded UploadedFile instances.
	 * This method is mainly used by test scripts to set up a fixture.
	 */
	public static function reset()
	{
		self::$_files = null;
	}

	/**
	 * Saves the uploaded file.
	 * Note that this method uses php's move_uploaded_file() method. If the target file `$file`
	 * already exists, it will be overwritten.
	 * @param string $file the file path used to save the uploaded file
	 * @param boolean $deleteTempFile whether to delete the temporary file after saving.
	 * If true, you will not be able to save the uploaded file again in the current request.
	 * @return boolean true whether the file is saved successfully
	 * @see error
	 */
	public function saveAs($file, $deleteTempFile = true)
	{
		if ($this->_error == UPLOAD_ERR_OK) {
			if ($deleteTempFile) {
				return move_uploaded_file($this->_tempName, $file);
			} elseif (is_uploaded_file($this->_tempName)) {
				return copy($this->_tempName, $file);
			}
		}
		return false;
	}

	/**
	 * @return string the original name of the file being uploaded
	 */
	public function getName()
	{
		return $this->_name;
	}

	/**
	 * @return string the path of the uploaded file on the server.
	 * Note, this is a temporary file which will be automatically deleted by PHP
	 * after the current request is processed.
	 */
	public function getTempName()
	{
		return $this->_tempName;
	}

	/**
	 * @return string the MIME-type of the uploaded file (such as "image/gif").
	 * Since this MIME type is not checked on the server side, do not take this value for granted.
	 * Instead, use [[FileHelper::getMimeType()]] to determine the exact MIME type.
	 */
	public function getType()
	{
		return $this->_type;
	}

	/**
	 * @return integer the actual size of the uploaded file in bytes
	 */
	public function getSize()
	{
		return $this->_size;
	}

	/**
	 * Returns an error code describing the status of this file uploading.
	 * @return integer the error code
	 * @see http://www.php.net/manual/en/features.file-upload.errors.php
	 */
	public function getError()
	{
		return $this->_error;
	}

	/**
	 * @return boolean whether there is an error with the uploaded file.
	 * Check [[error]] for detailed error code information.
	 */
	public function getHasError()
	{
		return $this->_error != UPLOAD_ERR_OK;
	}

	/**
	 * Creates UploadedFile instances from $_FILE.
	 * @return array the UploadedFile instances
	 */
	private static function loadFiles()
	{
		if (self::$_files === null) {
			self::$_files = array();
			if (isset($_FILES) && is_array($_FILES)) {
				foreach ($_FILES as $class => $info) {
					self::loadFilesRecursive($class, $info['name'], $info['tmp_name'], $info['type'], $info['size'], $info['error']);
				}
			}
		}
		return self::$_files;
	}

	/**
	 * Creates UploadedFile instances from $_FILE recursively.
	 * @param string $key key for identifying uploaded file: class name and sub-array indexes
	 * @param mixed $names file names provided by PHP
	 * @param mixed $tempNames temporary file names provided by PHP
	 * @param mixed $types file types provided by PHP
	 * @param mixed $sizes file sizes provided by PHP
	 * @param mixed $errors uploading issues provided by PHP
	 */
	private static function loadFilesRecursive($key, $names, $tempNames, $types, $sizes, $errors)
	{
		if (is_array($names)) {
			foreach ($names as $i => $name) {
				self::loadFilesRecursive($key . '[' . $i . ']', $name, $tempNames[$i], $types[$i], $sizes[$i], $errors[$i]);
			}
		} else {
			self::$_files[$key] = new self($names, $tempNames, $types, $sizes, $errors);
		}
	}
}