PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/Examples/Blog/Lib/ORG/UploadFile.class.php

http://thinkphp.googlecode.com/
PHP | 629 lines | 332 code | 35 blank | 262 comment | 64 complexity | fd750f831b7a8b891a27a5aa3f1a3582 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. // $Id: UploadFile.class.php 2601 2012-01-15 04:59:14Z liu21st $
  12. /**
  13. +------------------------------------------------------------------------------
  14. * ?????
  15. +------------------------------------------------------------------------------
  16. * @category ORG
  17. * @package ORG
  18. * @subpackage Net
  19. * @author liu21st <liu21st@gmail.com>
  20. * @version $Id: UploadFile.class.php 2601 2012-01-15 04:59:14Z liu21st $
  21. +------------------------------------------------------------------------------
  22. */
  23. class UploadFile {//?????
  24. // ????????
  25. public $maxSize = -1;
  26. // ?????????
  27. public $supportMulti = true;
  28. // ?????????
  29. // ????????
  30. public $allowExts = array();
  31. // ?????????
  32. // ??????
  33. public $allowTypes = array();
  34. // ??????????????
  35. public $thumb = false;
  36. // ??????
  37. public $imageClassPath = 'ORG.Util.Image';
  38. // ???????
  39. public $thumbMaxWidth;
  40. // ???????
  41. public $thumbMaxHeight;
  42. // ?????
  43. public $thumbPrefix = 'thumb_';
  44. public $thumbSuffix = '';
  45. // ???????
  46. public $thumbPath = '';
  47. // ??????
  48. public $thumbFile = '';
  49. // ??????
  50. public $thumbRemoveOrigin = false;
  51. // ????????
  52. public $zipImages = false;
  53. // ?????????
  54. public $autoSub = false;
  55. // ??????? ????hash date
  56. public $subType = 'hash';
  57. public $dateFormat = 'Ymd';
  58. public $hashLevel = 1; // hash?????
  59. // ????????
  60. public $savePath = '';
  61. public $autoCheck = true; // ????????
  62. // ????????
  63. public $uploadReplace = false;
  64. // ????????
  65. // ????? time uniqid com_create_guid ?
  66. // ??????????????? ?????????
  67. public $saveRule = '';
  68. // ????Hash?????
  69. // ????? md5_file sha1_file ?
  70. public $hashType = 'md5_file';
  71. // ????
  72. private $error = '';
  73. // ?????????
  74. private $uploadFileInfo ;
  75. /**
  76. +----------------------------------------------------------
  77. * ????
  78. +----------------------------------------------------------
  79. * @access public
  80. +----------------------------------------------------------
  81. */
  82. public function __construct($maxSize='',$allowExts='',$allowTypes='',$savePath='',$saveRule='') {
  83. if(!empty($maxSize) && is_numeric($maxSize)) {
  84. $this->maxSize = $maxSize;
  85. }
  86. if(!empty($allowExts)) {
  87. if(is_array($allowExts)) {
  88. $this->allowExts = array_map('strtolower',$allowExts);
  89. }else {
  90. $this->allowExts = explode(',',strtolower($allowExts));
  91. }
  92. }
  93. if(!empty($allowTypes)) {
  94. if(is_array($allowTypes)) {
  95. $this->allowTypes = array_map('strtolower',$allowTypes);
  96. }else {
  97. $this->allowTypes = explode(',',strtolower($allowTypes));
  98. }
  99. }
  100. if(!empty($saveRule)) {
  101. $this->saveRule = $saveRule;
  102. }else{
  103. $this->saveRule = C('UPLOAD_FILE_RULE');
  104. }
  105. $this->savePath = $savePath;
  106. }
  107. /**
  108. +----------------------------------------------------------
  109. * ??????
  110. +----------------------------------------------------------
  111. * @access public
  112. +----------------------------------------------------------
  113. * @param mixed $name ??
  114. * @param string $value ????
  115. +----------------------------------------------------------
  116. * @return string
  117. +----------------------------------------------------------
  118. * @throws ThinkExecption
  119. +----------------------------------------------------------
  120. */
  121. private function save($file) {
  122. $filename = $file['savepath'].$file['savename'];
  123. if(!$this->uploadReplace && is_file($filename)) {
  124. // ???????
  125. $this->error = '???????'.$filename;
  126. return false;
  127. }
  128. // ??????? ??????
  129. if( in_array(strtolower($file['extension']),array('gif','jpg','jpeg','bmp','png','swf')) && false === getimagesize($file['tmp_name'])) {
  130. $this->error = '??????';
  131. return false;
  132. }
  133. if(!move_uploaded_file($file['tmp_name'], $this->autoCharset($filename,'utf-8','gbk'))) {
  134. $this->error = '?????????';
  135. return false;
  136. }
  137. if($this->thumb && in_array(strtolower($file['extension']),array('gif','jpg','jpeg','bmp','png'))) {
  138. $image = getimagesize($filename);
  139. if(false !== $image) {
  140. //??????????
  141. $thumbWidth = explode(',',$this->thumbMaxWidth);
  142. $thumbHeight = explode(',',$this->thumbMaxHeight);
  143. $thumbPrefix = explode(',',$this->thumbPrefix);
  144. $thumbSuffix = explode(',',$this->thumbSuffix);
  145. $thumbFile = explode(',',$this->thumbFile);
  146. $thumbPath = $this->thumbPath?$this->thumbPath:$file['savepath'];
  147. // ???????
  148. import($this->imageClassPath);
  149. $realFilename = $this->autoSub?basename($file['savename']):$file['savename'];
  150. for($i=0,$len=count($thumbWidth); $i<$len; $i++) {
  151. $thumbname = $thumbPath.$thumbPrefix[$i].substr($realFilename,0,strrpos($realFilename, '.')).$thumbSuffix[$i].'.'.$file['extension'];
  152. Image::thumb($filename,$thumbname,'',$thumbWidth[$i],$thumbHeight[$i],true);
  153. }
  154. if($this->thumbRemoveOrigin) {
  155. // ???????????
  156. unlink($filename);
  157. }
  158. }
  159. }
  160. if($this->zipImags) {
  161. // TODO ??????????
  162. }
  163. return true;
  164. }
  165. /**
  166. +----------------------------------------------------------
  167. * ??????
  168. +----------------------------------------------------------
  169. * @access public
  170. +----------------------------------------------------------
  171. * @param string $savePath ????????
  172. +----------------------------------------------------------
  173. * @return string
  174. +----------------------------------------------------------
  175. * @throws ThinkExecption
  176. +----------------------------------------------------------
  177. */
  178. public function upload($savePath ='') {
  179. //?????????????????
  180. if(empty($savePath))
  181. $savePath = $this->savePath;
  182. // ??????
  183. if(!is_dir($savePath)) {
  184. // ??????????
  185. if(is_dir(base64_decode($savePath))) {
  186. $savePath = base64_decode($savePath);
  187. }else{
  188. // ??????
  189. if(!mkdir($savePath)){
  190. $this->error = '????'.$savePath.'???';
  191. return false;
  192. }
  193. }
  194. }else {
  195. if(!is_writeable($savePath)) {
  196. $this->error = '????'.$savePath.'???';
  197. return false;
  198. }
  199. }
  200. $fileInfo = array();
  201. $isUpload = false;
  202. // ?????????
  203. // ?$_FILES??????
  204. $files = $this->dealFiles($_FILES);
  205. foreach($files as $key => $file) {
  206. //???????
  207. if(!empty($file['name'])) {
  208. //???????????
  209. $file['key'] = $key;
  210. $file['extension'] = $this->getExt($file['name']);
  211. $file['savepath'] = $savePath;
  212. $file['savename'] = $this->getSaveName($file);
  213. // ??????
  214. if($this->autoCheck) {
  215. if(!$this->check($file))
  216. return false;
  217. }
  218. //??????
  219. if(!$this->save($file)) return false;
  220. if(function_exists($this->hashType)) {
  221. $fun = $this->hashType;
  222. $file['hash'] = $fun($this->autoCharset($file['savepath'].$file['savename'],'utf-8','gbk'));
  223. }
  224. //???????????????????
  225. unset($file['tmp_name'],$file['error']);
  226. $fileInfo[] = $file;
  227. $isUpload = true;
  228. }
  229. }
  230. if($isUpload) {
  231. $this->uploadFileInfo = $fileInfo;
  232. return true;
  233. }else {
  234. $this->error = '????????';
  235. return false;
  236. }
  237. }
  238. /**
  239. +----------------------------------------------------------
  240. * ???????????? ?????
  241. +----------------------------------------------------------
  242. * @access public
  243. +----------------------------------------------------------
  244. * @param array $file ??????
  245. * @param string $savePath ????????
  246. +----------------------------------------------------------
  247. * @return string
  248. +----------------------------------------------------------
  249. * @throws ThinkExecption
  250. +----------------------------------------------------------
  251. */
  252. public function uploadOne($file,$savePath=''){
  253. //?????????????????
  254. if(empty($savePath))
  255. $savePath = $this->savePath;
  256. // ??????
  257. if(!is_dir($savePath)) {
  258. // ??????
  259. if(!mk_dir($savePath)){
  260. $this->error = '????'.$savePath.'???';
  261. return false;
  262. }
  263. }else {
  264. if(!is_writeable($savePath)) {
  265. $this->error = '????'.$savePath.'???';
  266. return false;
  267. }
  268. }
  269. //???????
  270. if(!empty($file['name'])) {
  271. $fileArray = array();
  272. if(is_array($file['name'])) {
  273. $keys = array_keys($file);
  274. $count = count($file['name']);
  275. for ($i=0; $i<$count; $i++) {
  276. foreach ($keys as $key)
  277. $fileArray[$i][$key] = $file[$key][$i];
  278. }
  279. }else{
  280. $fileArray[] = $file;
  281. }
  282. $info = array();
  283. foreach ($fileArray as $key=>$file){
  284. //???????????
  285. $file['extension'] = $this->getExt($file['name']);
  286. $file['savepath'] = $savePath;
  287. $file['savename'] = $this->getSaveName($file);
  288. // ??????
  289. if($this->autoCheck) {
  290. if(!$this->check($file))
  291. return false;
  292. }
  293. //??????
  294. if(!$this->save($file)) return false;
  295. if(function_exists($this->hashType)) {
  296. $fun = $this->hashType;
  297. $file['hash'] = $fun($this->autoCharset($file['savepath'].$file['savename'],'utf-8','gbk'));
  298. }
  299. unset($file['tmp_name'],$file['error']);
  300. $info[] = $file;
  301. }
  302. // ?????????
  303. return $info;
  304. }else {
  305. $this->error = '????????';
  306. return false;
  307. }
  308. }
  309. /**
  310. +----------------------------------------------------------
  311. * ????????????????
  312. +----------------------------------------------------------
  313. * @access private
  314. +----------------------------------------------------------
  315. * @param array $files ???????
  316. +----------------------------------------------------------
  317. * @return array
  318. +----------------------------------------------------------
  319. */
  320. private function dealFiles($files) {
  321. $fileArray = array();
  322. $n = 0;
  323. foreach ($files as $file){
  324. if(is_array($file['name'])) {
  325. $keys = array_keys($file);
  326. $count = count($file['name']);
  327. for ($i=0; $i<$count; $i++) {
  328. foreach ($keys as $key)
  329. $fileArray[$n][$key] = $file[$key][$i];
  330. $n++;
  331. }
  332. }else{
  333. $fileArray[$n] = $file;
  334. $n++;
  335. }
  336. }
  337. return $fileArray;
  338. }
  339. /**
  340. +----------------------------------------------------------
  341. * ????????
  342. +----------------------------------------------------------
  343. * @access public
  344. +----------------------------------------------------------
  345. * @param string $errorNo ????
  346. +----------------------------------------------------------
  347. * @return void
  348. +----------------------------------------------------------
  349. * @throws ThinkExecption
  350. +----------------------------------------------------------
  351. */
  352. protected function error($errorNo) {
  353. switch($errorNo) {
  354. case 1:
  355. $this->error = '???????? php.ini ? upload_max_filesize ??????';
  356. break;
  357. case 2:
  358. $this->error = '?????????? HTML ??? MAX_FILE_SIZE ??????';
  359. break;
  360. case 3:
  361. $this->error = '?????????';
  362. break;
  363. case 4:
  364. $this->error = '???????';
  365. break;
  366. case 6:
  367. $this->error = '????????';
  368. break;
  369. case 7:
  370. $this->error = '??????';
  371. break;
  372. default:
  373. $this->error = '???????';
  374. }
  375. return ;
  376. }
  377. /**
  378. +----------------------------------------------------------
  379. * ?????????????????
  380. +----------------------------------------------------------
  381. * @access private
  382. +----------------------------------------------------------
  383. * @param string $filename ??
  384. +----------------------------------------------------------
  385. * @return string
  386. +----------------------------------------------------------
  387. */
  388. private function getSaveName($filename) {
  389. $rule = $this->saveRule;
  390. if(empty($rule)) {//?????????????????
  391. $saveName = $filename['name'];
  392. }else {
  393. if(function_exists($rule)) {
  394. //???????????????
  395. $saveName = $rule().".".$filename['extension'];
  396. }else {
  397. //?????????????
  398. $saveName = $rule.".".$filename['extension'];
  399. }
  400. }
  401. if($this->autoSub) {
  402. // ?????????
  403. $filename['savename'] = $saveName;
  404. $saveName = $this->getSubName($filename).'/'.$saveName;
  405. }
  406. return $saveName;
  407. }
  408. /**
  409. +----------------------------------------------------------
  410. * ????????
  411. +----------------------------------------------------------
  412. * @access private
  413. +----------------------------------------------------------
  414. * @param array $file ???????
  415. +----------------------------------------------------------
  416. * @return string
  417. +----------------------------------------------------------
  418. */
  419. private function getSubName($file) {
  420. switch($this->subType) {
  421. case 'date':
  422. $dir = date($this->dateFormat,time());
  423. break;
  424. case 'hash':
  425. default:
  426. $name = md5($file['savename']);
  427. $dir = '';
  428. for($i=0;$i<$this->hashLevel;$i++) {
  429. $dir .= $name{$i}.'/';
  430. }
  431. break;
  432. }
  433. if(!is_dir($file['savepath'].$dir)) {
  434. mk_dir($file['savepath'].$dir);
  435. }
  436. return $dir;
  437. }
  438. /**
  439. +----------------------------------------------------------
  440. * ???????
  441. +----------------------------------------------------------
  442. * @access private
  443. +----------------------------------------------------------
  444. * @param array $file ????
  445. +----------------------------------------------------------
  446. * @return boolean
  447. +----------------------------------------------------------
  448. */
  449. private function check($file) {
  450. if($file['error']!== 0) {
  451. //??????
  452. //??????
  453. $this->error($file['error']);
  454. return false;
  455. }
  456. //????????????????
  457. //??????
  458. if(!$this->checkSize($file['size'])) {
  459. $this->error = '?????????';
  460. return false;
  461. }
  462. //????Mime??
  463. if(!$this->checkType($file['type'])) {
  464. $this->error = '????MIME??????';
  465. return false;
  466. }
  467. //??????
  468. if(!$this->checkExt($file['extension'])) {
  469. $this->error ='?????????';
  470. return false;
  471. }
  472. //????????
  473. if(!$this->checkUpload($file['tmp_name'])) {
  474. $this->error = '???????';
  475. return false;
  476. }
  477. return true;
  478. }
  479. // ??????? ??????
  480. private function autoCharset($fContents, $from='gbk', $to='utf-8') {
  481. $from = strtoupper($from) == 'UTF8' ? 'utf-8' : $from;
  482. $to = strtoupper($to) == 'UTF8' ? 'utf-8' : $to;
  483. if (strtoupper($from) === strtoupper($to) || empty($fContents) || (is_scalar($fContents) && !is_string($fContents))) {
  484. //??????????????????
  485. return $fContents;
  486. }
  487. if (function_exists('mb_convert_encoding')) {
  488. return mb_convert_encoding($fContents, $to, $from);
  489. } elseif (function_exists('iconv')) {
  490. return iconv($from, $to, $fContents);
  491. } else {
  492. return $fContents;
  493. }
  494. }
  495. /**
  496. +----------------------------------------------------------
  497. * ?????????????
  498. +----------------------------------------------------------
  499. * @access private
  500. +----------------------------------------------------------
  501. * @param string $type ??
  502. +----------------------------------------------------------
  503. * @return boolean
  504. +----------------------------------------------------------
  505. */
  506. private function checkType($type) {
  507. if(!empty($this->allowTypes))
  508. return in_array(strtolower($type),$this->allowTypes);
  509. return true;
  510. }
  511. /**
  512. +----------------------------------------------------------
  513. * ?????????????
  514. +----------------------------------------------------------
  515. * @access private
  516. +----------------------------------------------------------
  517. * @param string $ext ???
  518. +----------------------------------------------------------
  519. * @return boolean
  520. +----------------------------------------------------------
  521. */
  522. private function checkExt($ext) {
  523. if(!empty($this->allowExts))
  524. return in_array(strtolower($ext),$this->allowExts,true);
  525. return true;
  526. }
  527. /**
  528. +----------------------------------------------------------
  529. * ??????????
  530. +----------------------------------------------------------
  531. * @access private
  532. +----------------------------------------------------------
  533. * @param integer $size ??
  534. +----------------------------------------------------------
  535. * @return boolean
  536. +----------------------------------------------------------
  537. */
  538. private function checkSize($size) {
  539. return !($size > $this->maxSize) || (-1 == $this->maxSize);
  540. }
  541. /**
  542. +----------------------------------------------------------
  543. * ??????????
  544. +----------------------------------------------------------
  545. * @access private
  546. +----------------------------------------------------------
  547. * @param string $filename ???
  548. +----------------------------------------------------------
  549. * @return boolean
  550. +----------------------------------------------------------
  551. */
  552. private function checkUpload($filename) {
  553. return is_uploaded_file($filename);
  554. }
  555. /**
  556. +----------------------------------------------------------
  557. * ?????????
  558. +----------------------------------------------------------
  559. * @access private
  560. +----------------------------------------------------------
  561. * @param string $filename ???
  562. +----------------------------------------------------------
  563. * @return boolean
  564. +----------------------------------------------------------
  565. */
  566. private function getExt($filename) {
  567. $pathinfo = pathinfo($filename);
  568. return $pathinfo['extension'];
  569. }
  570. /**
  571. +----------------------------------------------------------
  572. * ?????????
  573. +----------------------------------------------------------
  574. * @access public
  575. +----------------------------------------------------------
  576. * @return array
  577. +----------------------------------------------------------
  578. */
  579. public function getUploadFileInfo() {
  580. return $this->uploadFileInfo;
  581. }
  582. /**
  583. +----------------------------------------------------------
  584. * ??????????
  585. +----------------------------------------------------------
  586. * @access public
  587. +----------------------------------------------------------
  588. * @return string
  589. +----------------------------------------------------------
  590. */
  591. public function getErrorMsg() {
  592. return $this->error;
  593. }
  594. }