CUploadedFile.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <?php
  2. /**
  3. * CUploadedFile class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CUploadedFile represents the information for an uploaded file.
  12. *
  13. * Call {@link getInstance} to retrieve the instance of an uploaded file,
  14. * and then use {@link saveAs} to save it on the server.
  15. * You may also query other information about the file, including {@link name},
  16. * {@link tempName}, {@link type}, {@link size} and {@link error}.
  17. *
  18. * @property string $name The original name of the file being uploaded.
  19. * @property string $tempName The path of the uploaded file on the server.
  20. * Note, this is a temporary file which will be automatically deleted by PHP
  21. * after the current request is processed.
  22. * @property string $type The MIME-type of the uploaded file (such as "image/gif").
  23. * Since this MIME type is not checked on the server side, do not take this value for granted.
  24. * Instead, use {@link CFileHelper::getMimeType} to determine the exact MIME type.
  25. * @property integer $size The actual size of the uploaded file in bytes.
  26. * @property integer $error The error code.
  27. * @property boolean $hasError Whether there is an error with the uploaded file.
  28. * Check {@link error} for detailed error code information.
  29. * @property string $extensionName The file extension name for {@link name}.
  30. * The extension name does not include the dot character. An empty string
  31. * is returned if {@link name} does not have an extension name.
  32. *
  33. * @author Qiang Xue <qiang.xue@gmail.com>
  34. * @package system.web
  35. * @since 1.0
  36. */
  37. class CUploadedFile extends CComponent
  38. {
  39. static private $_files;
  40. private $_name;
  41. private $_tempName;
  42. private $_type;
  43. private $_size;
  44. private $_error;
  45. /**
  46. * Returns an instance of the specified uploaded file.
  47. * The file should be uploaded using {@link CHtml::activeFileField}.
  48. * @param CModel $model the model instance
  49. * @param string $attribute the attribute name. For tabular file uploading, this can be in the format of "[$i]attributeName", where $i stands for an integer index.
  50. * @return CUploadedFile the instance of the uploaded file.
  51. * Null is returned if no file is uploaded for the specified model attribute.
  52. * @see getInstanceByName
  53. */
  54. public static function getInstance($model, $attribute)
  55. {
  56. return self::getInstanceByName(CHtml::resolveName($model, $attribute));
  57. }
  58. /**
  59. * Returns all uploaded files for the given model attribute.
  60. * @param CModel $model the model instance
  61. * @param string $attribute the attribute name. For tabular file uploading, this can be in the format of "[$i]attributeName", where $i stands for an integer index.
  62. * @return CUploadedFile[] array of CUploadedFile objects.
  63. * Empty array is returned if no available file was found for the given attribute.
  64. */
  65. public static function getInstances($model, $attribute)
  66. {
  67. return self::getInstancesByName(CHtml::resolveName($model, $attribute));
  68. }
  69. /**
  70. * Returns an instance of the specified uploaded file.
  71. * The name can be a plain string or a string like an array element (e.g. 'Post[imageFile]', or 'Post[0][imageFile]').
  72. * @param string $name the name of the file input field.
  73. * @return CUploadedFile the instance of the uploaded file.
  74. * Null is returned if no file is uploaded for the specified name.
  75. */
  76. public static function getInstanceByName($name)
  77. {
  78. if(null===self::$_files)
  79. self::prefetchFiles();
  80. return isset(self::$_files[$name]) && self::$_files[$name]->getError()!=UPLOAD_ERR_NO_FILE ? self::$_files[$name] : null;
  81. }
  82. /**
  83. * Returns an array of instances starting with specified array name.
  84. *
  85. * If multiple files were uploaded and saved as 'Files[0]', 'Files[1]',
  86. * 'Files[n]'..., you can have them all by passing 'Files' as array name.
  87. * @param string $name the name of the array of files
  88. * @return CUploadedFile[] the array of CUploadedFile objects. Empty array is returned
  89. * if no adequate upload was found. Please note that this array will contain
  90. * all files from all subarrays regardless how deeply nested they are.
  91. */
  92. public static function getInstancesByName($name)
  93. {
  94. if(null===self::$_files)
  95. self::prefetchFiles();
  96. $len=strlen($name);
  97. $results=array();
  98. foreach(array_keys(self::$_files) as $key)
  99. if(0===strncmp($key, $name.'[', $len+1) && self::$_files[$key]->getError()!=UPLOAD_ERR_NO_FILE)
  100. $results[] = self::$_files[$key];
  101. return $results;
  102. }
  103. /**
  104. * Cleans up the loaded CUploadedFile instances.
  105. * This method is mainly used by test scripts to set up a fixture.
  106. * @since 1.1.4
  107. */
  108. public static function reset()
  109. {
  110. self::$_files=null;
  111. }
  112. /**
  113. * Initially processes $_FILES superglobal for easier use.
  114. * Only for internal usage.
  115. */
  116. protected static function prefetchFiles()
  117. {
  118. self::$_files = array();
  119. if(!isset($_FILES) || !is_array($_FILES))
  120. return;
  121. foreach($_FILES as $class=>$info)
  122. self::collectFilesRecursive($class, $info['name'], $info['tmp_name'], $info['type'], $info['size'], $info['error']);
  123. }
  124. /**
  125. * Processes incoming files for {@link getInstanceByName}.
  126. * @param string $key key for identifiing uploaded file: class name and subarray indexes
  127. * @param mixed $names file names provided by PHP
  128. * @param mixed $tmp_names temporary file names provided by PHP
  129. * @param mixed $types filetypes provided by PHP
  130. * @param mixed $sizes file sizes provided by PHP
  131. * @param mixed $errors uploading issues provided by PHP
  132. */
  133. protected static function collectFilesRecursive($key, $names, $tmp_names, $types, $sizes, $errors)
  134. {
  135. if(is_array($names))
  136. {
  137. foreach($names as $item=>$name)
  138. self::collectFilesRecursive($key.'['.$item.']', $names[$item], $tmp_names[$item], $types[$item], $sizes[$item], $errors[$item]);
  139. }
  140. else
  141. self::$_files[$key] = new CUploadedFile($names, $tmp_names, $types, $sizes, $errors);
  142. }
  143. /**
  144. * Constructor.
  145. * Use {@link getInstance} to get an instance of an uploaded file.
  146. * @param string $name the original name of the file being uploaded
  147. * @param string $tempName the path of the uploaded file on the server.
  148. * @param string $type the MIME-type of the uploaded file (such as "image/gif").
  149. * @param integer $size the actual size of the uploaded file in bytes
  150. * @param integer $error the error code
  151. */
  152. public function __construct($name,$tempName,$type,$size,$error)
  153. {
  154. $this->_name=$name;
  155. $this->_tempName=$tempName;
  156. $this->_type=$type;
  157. $this->_size=$size;
  158. $this->_error=$error;
  159. }
  160. /**
  161. * String output.
  162. * This is PHP magic method that returns string representation of an object.
  163. * The implementation here returns the uploaded file's name.
  164. * @return string the string representation of the object
  165. */
  166. public function __toString()
  167. {
  168. return $this->_name;
  169. }
  170. /**
  171. * Saves the uploaded file.
  172. * Note: this method uses php's move_uploaded_file() method. As such, if the target file ($file)
  173. * already exists it is overwritten.
  174. * @param string $file the file path used to save the uploaded file
  175. * @param boolean $deleteTempFile whether to delete the temporary file after saving.
  176. * If true, you will not be able to save the uploaded file again in the current request.
  177. * @return boolean true whether the file is saved successfully
  178. */
  179. public function saveAs($file,$deleteTempFile=true)
  180. {
  181. if($this->_error==UPLOAD_ERR_OK)
  182. {
  183. if($deleteTempFile)
  184. return move_uploaded_file($this->_tempName,$file);
  185. elseif(is_uploaded_file($this->_tempName))
  186. return copy($this->_tempName, $file);
  187. else
  188. return false;
  189. }
  190. else
  191. return false;
  192. }
  193. /**
  194. * @return string the original name of the file being uploaded
  195. */
  196. public function getName()
  197. {
  198. return $this->_name;
  199. }
  200. /**
  201. * @return string the path of the uploaded file on the server.
  202. * Note, this is a temporary file which will be automatically deleted by PHP
  203. * after the current request is processed.
  204. */
  205. public function getTempName()
  206. {
  207. return $this->_tempName;
  208. }
  209. /**
  210. * @return string the MIME-type of the uploaded file (such as "image/gif").
  211. * Since this MIME type is not checked on the server side, do not take this value for granted.
  212. * Instead, use {@link CFileHelper::getMimeType} to determine the exact MIME type.
  213. */
  214. public function getType()
  215. {
  216. return $this->_type;
  217. }
  218. /**
  219. * @return integer the actual size of the uploaded file in bytes
  220. */
  221. public function getSize()
  222. {
  223. return $this->_size;
  224. }
  225. /**
  226. * Returns an error code describing the status of this file uploading.
  227. * @return integer the error code
  228. * @see http://www.php.net/manual/en/features.file-upload.errors.php
  229. */
  230. public function getError()
  231. {
  232. return $this->_error;
  233. }
  234. /**
  235. * @return boolean whether there is an error with the uploaded file.
  236. * Check {@link error} for detailed error code information.
  237. */
  238. public function getHasError()
  239. {
  240. return $this->_error!=UPLOAD_ERR_OK;
  241. }
  242. /**
  243. * @return string the file extension name for {@link name}.
  244. * The extension name does not include the dot character. An empty string
  245. * is returned if {@link name} does not have an extension name.
  246. */
  247. public function getExtensionName()
  248. {
  249. return CFileHelper::getExtension($this->_name);
  250. }
  251. }