PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/wind/upload/AbstractWindUpload.php

https://github.com/cuijinquan/nextwind
PHP | 273 lines | 107 code | 21 blank | 145 comment | 20 complexity | f3615f3f75d10001dad8e6e5ad3116e4 MD5 | raw file
  1. <?php
  2. Wind::import('WIND:utility.Security');
  3. Wind::import('WIND:utility.WindFile');
  4. /**
  5. * 文件上传基类
  6. *
  7. * @author xiaoxia.xu <xiaoxia.xuxx@aliyun-inc.com>
  8. * @copyright ©2003-2103 phpwind.com
  9. * @license http://www.windframework.com
  10. * @version $Id: AbstractWindUpload.php 3172 2011-11-24 07:57:52Z yishuo $
  11. * @package upload
  12. */
  13. abstract class AbstractWindUpload {
  14. /**
  15. * 是否有错误产生
  16. *
  17. * @var boolean
  18. */
  19. protected $hasError = false;
  20. /**
  21. * 错误信息
  22. *
  23. * @var array
  24. */
  25. protected $errorInfo = array('type' => array(), 'size' => array(), 'upload' => array());
  26. /**
  27. * 允许的类型
  28. *
  29. * @var array
  30. */
  31. protected $allowType = array();//允许上传的类型及对应的大小,array(ext=>size);
  32. /**
  33. * 上传文件
  34. *
  35. * @param string $saveDir 文件保存的目录
  36. * @param string $preFileName 文件保存的前缀
  37. * @param array $allowType 允许的格式array(ext=>size) size单位为b
  38. * <code>
  39. * array(
  40. * 'jpg' => 1024,
  41. * 'gif => 1000,
  42. * </code>
  43. * @return array 返回上传成功的文件
  44. */
  45. public function upload($saveDir, $preFileName = '', $allowType = array()) {
  46. $this->setAllowType($allowType);
  47. $uploaddb = array();
  48. foreach ($_FILES as $key => $value) {
  49. if (is_array($value['name'])) {
  50. $temp = $this->multiUpload($key, $saveDir, $preFileName);
  51. $uploaddb[$key] = isset($uploaddb[$key]) ? array_merge((array)$uploaddb[$key], $temp) : $temp;
  52. } else {
  53. $uploaddb[$key][] = $this->simpleUpload($key, $saveDir, $preFileName);
  54. }
  55. }
  56. return 1 == count($uploaddb) ? array_shift($uploaddb) : $uploaddb;
  57. }
  58. /**
  59. * 多文件上传
  60. *
  61. * 多个控件
  62. * 一个表单中拥有多个上传文件的控件
  63. *
  64. * @param string $key 文件的key
  65. * @param string $saveDir 文件保存的目录
  66. * @param string $preFileName 保存文件的前缀默认为空字串
  67. * @return array 返回上传成功之后的文件信息
  68. */
  69. private function simpleUpload($key, $saveDir, $preFileName = '') {
  70. return $this->doUp($key, $_FILES[$key], $saveDir, $preFileName);
  71. }
  72. /**
  73. * 多文件上传
  74. *
  75. * 多个控件
  76. * 一个表单中拥有多个上传文件的控件
  77. *
  78. * @param string $key 文件的key
  79. * @param string $saveDir 文件保存的目录
  80. * @param string $preFileName 保存文件的前缀默认为空字串
  81. * @return array 返回上传成功之后的文件信息
  82. */
  83. private function multiUpload($key, $saveDir, $preFileName = '') {
  84. $uploaddb = array();
  85. $files = $_FILES[$key];
  86. $num = count($files['name']);
  87. for($i = 0; $i < $num; $i ++) {
  88. $one = array();
  89. $one['name'] = $files['name'][$i];
  90. $one['tmp_name'] = $files['tmp_name'][$i];
  91. $one['error'] = $files['error'][$i];
  92. $one['size'] = $files['size'][$i];
  93. $one['type'] = $files['type'][$i];
  94. if (!($upload = $this->doUp($key, $one, $saveDir, $preFileName))) continue;
  95. $uploaddb[] = $upload;
  96. }
  97. return $uploaddb;
  98. }
  99. /**
  100. * 执行上传操作
  101. *
  102. * @param string $tmp_name 临时文件
  103. * @param string $filename 目的文件名
  104. * @return bool
  105. */
  106. abstract protected function postUpload($tmp_name, $filename);
  107. /**
  108. * 返回是否含有错误
  109. *
  110. * @return boolean
  111. */
  112. public function hasError() {
  113. return $this->hasError;
  114. }
  115. /**
  116. * 返回错误信息
  117. *
  118. * @param string $errorType 错误类型,可选参数为:
  119. * <ul>
  120. * <li>'type': 类型出错而不能上传的文件信息,</li>
  121. * <li>'size': 超过指定大小而上传失败的文件信息<li>
  122. * <li>'upload': 文件不能上传过程出现错误的文件信息</li>
  123. * </ul>默认为空,则返回所有上述类型的错误信息
  124. * @return array
  125. */
  126. public function getErrorInfo($errorType = '') {
  127. return isset($this->errorInfo[$errorType]) ? $this->errorInfo[$errorType] : $this->errorInfo;
  128. }
  129. /**
  130. * 设置允许上传的类型
  131. *
  132. * @param array $allowType 允许上传的格式配置
  133. * @return void
  134. */
  135. public function setAllowType($allowType) {
  136. $allowType && $this->allowType = $allowType;
  137. }
  138. /**
  139. * 检查文件是否允许上传
  140. *
  141. * @param string $ext 文件的后缀
  142. * @return bool 如果在允许的范围则返回true,否则返回false
  143. */
  144. protected function checkAllowType($ext) {
  145. $allowType = array_keys((array)$this->allowType);
  146. return $allowType ? in_array($ext, $allowType) : true;
  147. }
  148. /**
  149. * 检查上传文件的大小
  150. *
  151. * @param string $type 文件的类型
  152. * @param string $uploadSize 上传文件的大小
  153. * @return bool 如果上传文件超过指定允许上传的大小则返回false,否则返回true
  154. */
  155. protected function checkAllowSize($type, $uploadSize) {
  156. if ($uploadSize < 0) return false;
  157. if (!$this->allowType || !$this->allowType[$type]) return true;
  158. return $uploadSize < $this->allowType[$type];
  159. }
  160. /**
  161. * 获得文件名字
  162. *
  163. * @param array $attInfo 上传文件的信息
  164. * @param string $preFileName 文件的前缀
  165. * @return string 上传文件的名字
  166. */
  167. protected function getFileName($attInfo, $preFileName = '') {
  168. $fileName = mt_rand(1, 10) . time() . substr(md5(time() . $attInfo['attname'] . mt_rand(1, 10)), 10, 15) . '.' . $attInfo['ext'];
  169. return $preFileName ? $preFileName . $fileName : $fileName;
  170. }
  171. /**
  172. * 获得保存路径
  173. *
  174. * @param string $fileName 保存的文件名字
  175. * @param string $saveDir 保存文件的路径
  176. * @return string 上传后的保存文件的完整路径
  177. */
  178. protected function getSavePath($fileName, $saveDir) {
  179. return $saveDir ? rtrim($saveDir, '\\/') . '/' . $fileName : $fileName;
  180. }
  181. /**
  182. * 判断是否有上传文件
  183. *
  184. * @param string $tmp_name 临时上传文件
  185. * @return boolean 如果该文件可以被上传则返回true,否则返回false
  186. */
  187. protected function isUploadFile($tmp_name) {
  188. if (!$tmp_name || $tmp_name == 'none') {
  189. return false;
  190. } elseif (function_exists('is_uploaded_file') && !is_uploaded_file($tmp_name) && !is_uploaded_file(str_replace('\\\\', '\\', $tmp_name))) {
  191. return false;
  192. } else {
  193. return true;
  194. }
  195. }
  196. /**
  197. * 初始化上传的文件信息
  198. *
  199. * @param string $key 上传文件的key
  200. * @param string $value 上传文件的信息
  201. * @param string $preFileName 上传文件的前缀
  202. * @param string $saveDir 上传文件保存路径
  203. * @return array 返回文件上传的信息
  204. */
  205. protected function initUploadInfo($key, $value, $preFileName, $saveDir) {
  206. $arr = array('attname' => $key, 'name' => $value['name'], 'size' => $value['size'], 'type' => $value['type'], 'ifthumb' => 0, 'fileuploadurl' => '');
  207. $arr['ext'] = strtolower(substr(strrchr($arr['name'], '.'), 1));
  208. $arr['filename'] = $this->getFileName($arr, $preFileName);
  209. $arr['fileuploadurl'] = $this->getSavePath($arr['filename'], $saveDir);
  210. return $arr;
  211. }
  212. /**
  213. * 判断是否使图片,如果使图片则返回
  214. *
  215. * @param string $ext 文件后缀
  216. * @return boolean 如果该文件允许被上传则返回true,否则返回false
  217. */
  218. protected function isImage($ext) {
  219. return in_array($ext, array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'swf'));
  220. }
  221. /**
  222. * 执行上传操作
  223. *
  224. * @param string $key 上传文件的Key值
  225. * @param array $value 文件的上传信息
  226. * @param string $saveDir 上传文件的保存路径
  227. * @param string $preFileName 上传文件的前缀
  228. * @return array 上传成功后的文件信息
  229. */
  230. protected function doUp($key, $value, $saveDir, $preFileName) {
  231. if (!$this->isUploadFile($value['tmp_name'])) return array();
  232. $upload = $this->initUploadInfo($key, $value, $preFileName, $saveDir);
  233. if (empty($upload['ext']) || !$this->checkAllowType($upload['ext'])) {
  234. $this->errorInfo['type'][$key][] = $upload;
  235. $this->hasError = true;
  236. return array();
  237. }
  238. if (!$this->checkAllowSize($upload['ext'], $upload['size'])) {
  239. $upload['maxSize'] = $this->allowType[$upload['ext']];
  240. $this->errorInfo['size'][$key][] = $upload;
  241. $this->hasError = true;
  242. return array();
  243. }
  244. if (!($uploadSize = $this->postUpload($value['tmp_name'], $upload['fileuploadurl']))) {
  245. $this->errorInfo['upload'][$key][] = $upload;
  246. $this->hasError = true;
  247. return array();
  248. }
  249. $upload['size'] = intval($uploadSize);
  250. return $upload;
  251. }
  252. }