Upload.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. <?php
  2. namespace Qii\Library;
  3. /**
  4. * Library upload_library
  5. * @author Jinhui Zhu <jinhui.zhu@live.cn>
  6. * @version 1.2
  7. *
  8. * 使用方法:
  9. * $libUpload = new \Qii\Library\Upload();
  10. * $libUpload->setAllowed(array('mp3', 'mp4'));
  11. * $uploaded_files = $libUpload->upload('file', array('path' => 'data/tmp',
  12. * 'maxSize' => 1024*1024,
  13. * 'maxFolder' => 100,
  14. * 'prefix' => '',
  15. * ));
  16. *
  17. */
  18. class Upload
  19. {
  20. const VERSION = '1.2';
  21. public $dir;
  22. public $name;
  23. public $allowed = array('jpg', 'gif', 'png');
  24. public $error;
  25. protected $errorMessage = array(
  26. 1 => '文件超出大小限制',
  27. 2 => '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值',
  28. 3 => '文件只有部分被上传',
  29. 4 => '没有文件被上传',
  30. 6 => '找不到临时文件夹',
  31. 7 => '文件写入失败',
  32. 8 => '上传被其它扩展中断'
  33. );
  34. public $mine = array(
  35. '*' => 'application/octet-stream',
  36. '323' => 'text/h323',
  37. 'acx' => 'application/internet-property-stream',
  38. 'ai' => 'application/postscript',
  39. 'aif' => 'audio/x-aiff',
  40. 'aifc' => 'audio/x-aiff',
  41. 'aiff' => 'audio/x-aiff',
  42. 'asf' => 'video/x-ms-asf',
  43. 'asr' => 'video/x-ms-asf',
  44. 'asx' => 'video/x-ms-asf',
  45. 'au' => 'audio/basic',
  46. 'avi' => 'video/x-msvideo',
  47. 'axs' => 'application/olescript',
  48. 'bas' => 'text/plain',
  49. 'bcpio' => 'application/x-bcpio',
  50. 'bin' => 'application/octet-stream',
  51. 'bmp' => 'image/bmp',
  52. 'c' => 'text/plain',
  53. 'cat' => 'application/vnd.ms-pkiseccat',
  54. 'cdf' => 'application/x-cdf',
  55. 'cer' => 'application/x-x509-ca-cert',
  56. 'class' => 'application/octet-stream',
  57. 'clp' => 'application/x-msclip',
  58. 'cmx' => 'image/x-cmx',
  59. 'cod' => 'image/cis-cod',
  60. 'cpio' => 'application/x-cpio',
  61. 'crd' => 'application/x-mscardfile',
  62. 'crl' => 'application/pkix-crl',
  63. 'crt' => 'application/x-x509-ca-cert',
  64. 'csh' => 'application/x-csh',
  65. 'css' => 'text/css',
  66. 'dcr' => 'application/x-director',
  67. 'der' => 'application/x-x509-ca-cert',
  68. 'dir' => 'application/x-director',
  69. 'dll' => 'application/x-msdownload',
  70. 'dms' => 'application/octet-stream',
  71. 'doc' => 'application/msword',
  72. 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  73. 'dot' => 'application/msword',
  74. 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
  75. 'dvi' => 'application/x-dvi',
  76. 'dxr' => 'application/x-director',
  77. 'eps' => 'application/postscript',
  78. 'etx' => 'text/x-setext',
  79. 'evy' => 'application/envoy',
  80. 'exe' => 'application/octet-stream',
  81. 'fif' => 'application/fractals',
  82. 'flr' => 'x-world/x-vrml',
  83. 'gif' => 'image/gif',
  84. 'gtar' => 'application/x-gtar',
  85. 'gz' => 'application/x-gzip',
  86. 'h' => 'text/plain',
  87. 'hdf' => 'application/x-hdf',
  88. 'hlp' => 'application/winhlp',
  89. 'hqx' => 'application/mac-binhex40',
  90. 'hta' => 'application/hta',
  91. 'htc' => 'text/x-component',
  92. 'htm' => 'text/html',
  93. 'html' => 'text/html',
  94. 'htt' => 'text/webviewhtml',
  95. 'ico' => 'image/x-icon',
  96. 'ief' => 'image/ief',
  97. 'iii' => 'application/x-iphone',
  98. 'ins' => 'application/x-internet-signup',
  99. 'isp' => 'application/x-internet-signup',
  100. 'jfif' => 'image/pipeg',
  101. 'jpe' => 'image/jpeg',
  102. 'jpeg' => 'image/jpeg',
  103. 'jpg' => 'image/jpeg',
  104. 'png' => 'image/png',
  105. 'js' => 'application/x-javascript',
  106. 'latex' => 'application/x-latex',
  107. 'lha' => 'application/octet-stream',
  108. 'lsf' => 'video/x-la-asf',
  109. 'lsx' => 'video/x-la-asf',
  110. 'lzh' => 'application/octet-stream',
  111. 'm13' => 'application/x-msmediaview',
  112. 'm14' => 'application/x-msmediaview',
  113. 'm3u' => 'audio/x-mpegurl',
  114. 'man' => 'application/x-troff-man',
  115. 'mdb' => 'application/x-msaccess',
  116. 'me' => 'application/x-troff-me',
  117. 'mht' => 'message/rfc822',
  118. 'mhtml' => 'message/rfc822',
  119. 'mid' => 'audio/mid',
  120. 'mny' => 'application/x-msmoney',
  121. 'mov' => 'video/quicktime',
  122. 'movie' => 'video/x-sgi-movie',
  123. 'mp2' => 'video/mpeg',
  124. 'mp3' => 'audio/mpeg',
  125. 'mpa' => 'video/mpeg',
  126. 'mpe' => 'video/mpeg',
  127. 'mpeg' => 'video/mpeg',
  128. 'mpg' => 'video/mpeg',
  129. 'mpp' => 'application/vnd.ms-project',
  130. 'mpv2' => 'video/mpeg',
  131. 'ms' => 'application/x-troff-ms',
  132. 'mvb' => 'application/x-msmediaview',
  133. 'nws' => 'message/rfc822',
  134. 'oda' => 'application/oda',
  135. 'p10' => 'application/pkcs10',
  136. 'p12' => 'application/x-pkcs12',
  137. 'p7b' => 'application/x-pkcs7-certificates',
  138. 'p7c' => 'application/x-pkcs7-mime',
  139. 'p7m' => 'application/x-pkcs7-mime',
  140. 'p7r' => 'application/x-pkcs7-certreqresp',
  141. 'p7s' => 'application/x-pkcs7-signature',
  142. 'pbm' => 'image/x-portable-bitmap',
  143. 'pdf' => 'application/pdf',
  144. 'pfx' => 'application/x-pkcs12',
  145. 'pgm' => 'image/x-portable-graymap',
  146. 'pko' => 'application/ynd.ms-pkipko',
  147. 'pma' => 'application/x-perfmon',
  148. 'pmc' => 'application/x-perfmon',
  149. 'pml' => 'application/x-perfmon',
  150. 'pmr' => 'application/x-perfmon',
  151. 'pmw' => 'application/x-perfmon',
  152. 'pnm' => 'image/x-portable-anymap',
  153. 'pot,' => 'application/vnd.ms-powerpoint',
  154. 'potx,' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
  155. 'ppm' => 'image/x-portable-pixmap',
  156. 'pps' => 'application/vnd.ms-powerpoint',
  157. 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshowt',
  158. 'ppt' => 'application/vnd.ms-powerpoint',
  159. 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
  160. 'prf' => 'application/pics-rules',
  161. 'ps' => 'application/postscript',
  162. 'pub' => 'application/x-mspublisher',
  163. 'qt' => 'video/quicktime',
  164. 'ra' => 'audio/x-pn-realaudio',
  165. 'ram' => 'audio/x-pn-realaudio',
  166. 'ras' => 'image/x-cmu-raster',
  167. 'rgb' => 'image/x-rgb',
  168. 'rmi' => 'audio/mid',
  169. 'roff' => 'application/x-troff',
  170. 'rtf' => 'application/rtf',
  171. 'rtx' => 'text/richtext',
  172. 'scd' => 'application/x-msschedule',
  173. 'sct' => 'text/scriptlet',
  174. 'setpay' => 'application/set-payment-initiation',
  175. 'setreg' => 'application/set-registration-initiation',
  176. 'sh' => 'application/x-sh',
  177. 'shar' => 'application/x-shar',
  178. 'sit' => 'application/x-stuffit',
  179. 'snd' => 'audio/basic',
  180. 'spc' => 'application/x-pkcs7-certificates',
  181. 'spl' => 'application/futuresplash',
  182. 'src' => 'application/x-wais-source',
  183. 'sst' => 'application/vnd.ms-pkicertstore',
  184. 'stl' => 'application/vnd.ms-pkistl',
  185. 'stm' => 'text/html',
  186. 'svg' => 'image/svg+xml',
  187. 'sv4cpio' => 'application/x-sv4cpio',
  188. 'sv4crc' => 'application/x-sv4crc',
  189. 'swf' => 'application/x-shockwave-flash',
  190. 't' => 'application/x-troff',
  191. 'tar' => 'application/x-tar',
  192. 'tcl' => 'application/x-tcl',
  193. 'tex' => 'application/x-tex',
  194. 'texi' => 'application/x-texinfo',
  195. 'texinfo' => 'application/x-texinfo',
  196. 'tgz' => 'application/x-compressed',
  197. 'tif' => 'image/tiff',
  198. 'tiff' => 'image/tiff',
  199. 'tr' => 'application/x-troff',
  200. 'trm' => 'application/x-msterminal',
  201. 'tsv' => 'text/tab-separated-values',
  202. 'txt' => 'text/plain',
  203. 'uls' => 'text/iuls',
  204. 'ustar' => 'application/x-ustar',
  205. 'vcf' => 'text/x-vcard',
  206. 'vrml' => 'x-world/x-vrml',
  207. 'wav' => 'audio/x-wav',
  208. 'wcm' => 'application/vnd.ms-works',
  209. 'wdb' => 'application/vnd.ms-works',
  210. 'wks' => 'application/vnd.ms-works',
  211. 'wmf' => 'application/x-msmetafile',
  212. 'wps' => 'application/vnd.ms-works',
  213. 'wri' => 'application/x-mswrite',
  214. 'wrl' => 'x-world/x-vrml',
  215. 'wrz' => 'x-world/x-vrml',
  216. 'xaf' => 'x-world/x-vrml',
  217. 'xbm' => 'image/x-xbitmap',
  218. 'xla' => 'application/vnd.ms-excel',
  219. 'xlc' => 'application/vnd.ms-excel',
  220. 'xlm' => 'application/vnd.ms-excel',
  221. 'xls' => 'application/vnd.ms-excel',
  222. 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  223. 'xlt' => 'application/vnd.ms-excel',
  224. 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
  225. 'xlw' => 'application/vnd.ms-excel',
  226. 'xof' => 'x-world/x-vrml',
  227. 'xpm' => 'image/x-xpixmap',
  228. 'xwd' => 'image/x-xwindowdump',
  229. 'z' => 'application/x-compress',
  230. 'zip' => 'application/zip',
  231. );
  232. public function __construct()
  233. {
  234. }
  235. /**
  236. * 设置允许上传的文件类型
  237. * @param array $array 允许上传的文件类型
  238. */
  239. public function setAllowed(array $array)
  240. {
  241. $this->allowed = $array;
  242. }
  243. /**
  244. * setError
  245. *
  246. * @param String $key
  247. * @param Mix $value
  248. */
  249. public function setError($key, $value)
  250. {
  251. $this->error[$key] = $value;
  252. }
  253. /**
  254. * 获取错误信息
  255. *
  256. * @param String $key
  257. * @return Mix
  258. */
  259. public function getError($key)
  260. {
  261. if (!empty($key)) {
  262. return $this->error[$key];
  263. }
  264. return $this->error;
  265. }
  266. /**
  267. * 上传过程中是否有错误
  268. */
  269. public function isError()
  270. {
  271. return count($this->error) > 0 ? true : false;
  272. }
  273. /**
  274. * 是否为二进制上传
  275. */
  276. public function isBinaryUpload()
  277. {
  278. return isset($_SERVER['HTTP_CONTENT_DISPOSITION'])
  279. && preg_match('/attachment;\s+name="(.+?)";\s+filename="(.+?)"/i',
  280. $_SERVER['HTTP_CONTENT_DISPOSITION']);
  281. }
  282. /**
  283. * html5上传
  284. */
  285. public function uploadBinary($configure)
  286. {
  287. $data = array();
  288. if (!is_array($configure) || empty($configure)) {
  289. $data['code'] = 1406;
  290. $data['src'] = '';
  291. $data['msg'] = 'Configure file is empty';
  292. return $data;
  293. }
  294. //如果文件路径不存在就自动创建
  295. if (!is_dir($configure['path'])) {
  296. mkdir($configure['path'], 0777, true);
  297. }
  298. if (!isset($configure['prefix'])) $configure['prefix'] = '';
  299. $tmpFile = sys_get_temp_dir() . DS . time() . rand(10000, 1000000);
  300. if (isset($_SERVER['HTTP_CONTENT_DISPOSITION'])
  301. && preg_match('/attachment;\s+name="(.+?)";\s+filename="(.+?)"/i',
  302. $_SERVER['HTTP_CONTENT_DISPOSITION'], $info)
  303. ) {
  304. file_put_contents($tmpFile, file_get_contents("php://input"));
  305. $name = urldecode($info[2]);
  306. }
  307. $file = array(
  308. 'binary' => true,
  309. 'name' => $name,
  310. 'type' => '',
  311. 'tmp_name' => $tmpFile,
  312. 'error' => 0,
  313. 'size' => filesize($tmpFile)
  314. );
  315. return $this->deal($file, $configure);
  316. }
  317. /**
  318. * 上传文件
  319. * @param $files
  320. * @param array $configure
  321. * @return array
  322. */
  323. protected function deal($files, $configure = array(), $index = 0)
  324. {
  325. $data = array();
  326. if (!is_array($configure) || empty($configure)) {
  327. $data['code'] = 1406;
  328. $data['src'] = '';
  329. $data['msg'] = 'Configure file is empty';
  330. return $data;
  331. }
  332. if (is_array($files['name'])) {
  333. foreach ($files['name'] as $key => $value) {
  334. $file = array(
  335. 'name' => $files['name'][$key],
  336. 'type' => $files['type'][$key],
  337. 'tmp_name' => $files['tmp_name'][$key],
  338. 'error' => $files['error'][$key],
  339. 'size' => $files['size'][$key]
  340. );
  341. $data['files'][] = $this->deal($file, $configure, $key);
  342. }
  343. return $data;
  344. }
  345. if (!isset($files['binary'])) $files['binary'] = false;
  346. if ($files['error'] != UPLOAD_ERR_OK) {
  347. $data['code'] = $files['error'];
  348. $data['src'] = '';
  349. $data['size'] = 0;
  350. $data['msg'] = $this->errorMessage[$files['error']];
  351. $this->setError($index, 100008);
  352. return $data;
  353. }
  354. $extension = pathinfo($files['name'], PATHINFO_EXTENSION);
  355. $extension = strtolower($extension);
  356. if (!in_array($files['type'], $this->mine) || !isset($this->mine[$extension])) {
  357. $data['code'] = 1407;
  358. $data['src'] = '';
  359. $data['size'] = 0;
  360. $data['extension'] = $extension;
  361. $data['msg'] = 'Not Allowed';
  362. return $data;
  363. }
  364. //如果设置允许所有文件上传就不检测
  365. if ($this->allowed[0] != '*' && !in_array($extension, $this->allowed)) {
  366. $data['code'] = 1407;
  367. $data['src'] = '';
  368. $data['size'] = 0;
  369. $data['extension'] = $extension;
  370. $data['msg'] = 'Not Allowed';
  371. return $data;
  372. }
  373. $extension = '.' . $extension;
  374. //如果是设置了保持文件名称的话,就不自动转换文件名
  375. if (isset($configure['keepFileName'])) {
  376. $fileName = pathinfo($files['name'], PATHINFO_FILENAME);
  377. } else {
  378. $fileName = rand(10000, 90000) . uniqid();
  379. }
  380. $configure['fileName'] = $configure['prefix'] . $fileName . $extension;
  381. $subDir = $this->distribution($fileName, $configure['maxFolder']);
  382. $fillPath = $configure['path'];
  383. if (!empty($subDir)) {
  384. $fillPath = $fillPath . '/' . $subDir;
  385. }
  386. if (!is_dir($fillPath)) {
  387. if (!mkdir($fillPath, 0777, true)) {
  388. $data['code'] = 100007;
  389. $data['src'] = 0;
  390. $data['msg'] = 'Access Denied';
  391. $this->setError($index, 100007);
  392. return $data;
  393. }
  394. }
  395. //将文件名转换成URL编码,防止移动文件不成功的情况
  396. $realPath = rtrim($fillPath, '/') . '/' . urlencode($configure['fileName']);
  397. if ($files['binary']) {
  398. $result = rename($files['tmp_name'], $realPath);
  399. } else {
  400. $result = move_uploaded_file($files['tmp_name'], $realPath);
  401. }
  402. if ($result) {
  403. $data['code'] = 0;
  404. $data['src'] = toUTF8($realPath);
  405. $data['name'] = toUTF8($files['name']);
  406. $data['file_type'] = $files['type'];
  407. $data['file_hash'] = md5_file($realPath);
  408. $data['size'] = $files['size'];
  409. } else {
  410. $data['src'] = '';
  411. $data['code'] = 100005;
  412. $data['msg'] = 100005;
  413. $data['size'] = 0;
  414. $this->setError($index, 100005);
  415. }
  416. return $data;
  417. }
  418. /**
  419. * 上传文件
  420. *
  421. * @param String $filed 上传文件域名称
  422. * @param Array $configure array('path' => 'data/tmp',
  423. * 'maxSize' => 1024*1024,
  424. * 'maxFolder' => 100);
  425. */
  426. public function upload($filed = 'upload', $configure)
  427. {
  428. $data = array();
  429. if ($_FILES[$filed]) {
  430. if (!is_dir($configure['path'])) {
  431. mkdir($configure['path'], 0777, true);
  432. }
  433. if (!isset($configure['prefix'])) $configure['prefix'] = '';
  434. return $this->deal($_FILES[$filed], $configure);
  435. }
  436. return $data;
  437. }
  438. /**
  439. * 自动重命名文件,如果没有指定目录就重命名,否则移动文件
  440. *
  441. * @param Mix $oldName 原始文件名
  442. * @param Mix $newName 新文件名
  443. * @param Bool $keepExtension 是否保持当前文件名
  444. * @return Array|String
  445. */
  446. public function rename($oldName, $newName, $keepExtension = false)
  447. {
  448. $path = array();
  449. if (is_array($oldName)) {
  450. foreach ($oldName AS $key => $val) {
  451. $path[] = autoRename($val, $newName[$key]);
  452. }
  453. } else {
  454. $oldNameArray = pathinfo($oldName);
  455. $newNameArray = pathinfo($newName);
  456. $dirName = $oldNameArray['dirname'];
  457. //如果第二个文件夹没有包含路径就直接重新命名,否则移动到新的路径下
  458. if ($newNameArray['dirname'] == substr($newName, 0, strlen($newNameArray['dirname']))) {
  459. $dirName = $newNameArray['dirname'];
  460. }
  461. $fileName = $oldNameArray['filename'];
  462. if ($newNameArray['filename']) {
  463. $fileName = $newNameArray['filename'];
  464. }
  465. $extension = '.' . $oldNameArray['extension'];
  466. if (!isset($newNameArray['extension']) && !$keepExtension) {
  467. $extension = '';
  468. }
  469. $newPath = $dirName . '/' . $fileName . $extension;
  470. rename($oldName, $newPath);
  471. return $newPath;
  472. }
  473. return $path;
  474. }
  475. /**
  476. * 过滤images
  477. *
  478. * @param Array $images
  479. * @return Array
  480. */
  481. public function filterImages($images)
  482. {
  483. $data = array();
  484. if (!is_array($images)) {
  485. return $data;
  486. }
  487. foreach ($images AS $image) {
  488. if (!empty($image)) $data[] = $image;
  489. }
  490. return $data;
  491. }
  492. /**
  493. * 根据配置文件批量缩放图片
  494. * @param $images 图片路径
  495. * @param $configure [{width: 100, height: 100}, ...]
  496. * @return array
  497. */
  498. public function autoResize($images, $configure)
  499. {
  500. $data = array();
  501. if (is_array($images)) {
  502. foreach ($images AS $image) {
  503. $data[] = $this->autoResize($image, $configure);
  504. }
  505. } else {
  506. $thumbs = array();
  507. foreach ($configure['size'] AS $key => $value) {
  508. $pathInfo = pathinfo($images);
  509. $thumbs[$key] = $small = $pathInfo['dirname'] . '/' . $pathInfo['filename'] . '.' . $key . '.' . $pathInfo['extension'];
  510. $this->imgCutScale($images, $small, $configure['size'][$key]['width'], $configure['size'][$key]['height']);
  511. $this->imgResizeSamll($small, $small, $configure['size'][$key]['width']);
  512. }
  513. return $thumbs;
  514. }
  515. return $data;
  516. }
  517. /**
  518. * 计算存放的文件夹
  519. *
  520. * @param String $fileName 文件名
  521. * @param Int $maxFolder 文件夹数量
  522. * @return String
  523. */
  524. public function distribution($fileName, $maxFolder = 100)
  525. {
  526. if (empty($maxFolder) || $maxFolder == 1) {
  527. return '';
  528. }
  529. $folder = ord($fileName) % $maxFolder;
  530. if ($folder == 0) {
  531. return $maxFolder;
  532. }
  533. return $folder;
  534. }
  535. /**
  536. * 图片缩放,等比缩放
  537. *
  538. * @param String $bigImg 原图
  539. * @param String $smallImg 缩放以后的图片
  540. * @param Int $width 宽度
  541. * @return Bool
  542. */
  543. public function imgResizeSmall($bigImg, $smallImg, $width = 392)
  544. {
  545. // 图片路径
  546. if (!file_exists($bigImg)) {
  547. $this->setError('img_resize_samll', $bigImg . "文件不存在");
  548. return false;
  549. } else {
  550. ini_set("memory_limit", "128M");
  551. $filename = $bigImg;
  552. // 获取原图片的尺寸
  553. list($widthOrig, $heightOrig) = getimagesize($filename);
  554. //根据比例,计算新图片的尺寸
  555. $height = ($width / $widthOrig) * $heightOrig;
  556. //新建一个真彩色图像
  557. $destImage = imagecreate($width, $height);
  558. //从 JPEG 文件或 URL 新建一图像
  559. $imageInfo = getimagesize($bigImg);//获取大图信息
  560. switch ($imageInfo[2]) {//判断图像类型
  561. case 1:
  562. $image = imagecreatefromgif($bigImg);
  563. break;
  564. case 2:
  565. $image = imagecreatefromjpeg($bigImg);
  566. break;
  567. case 3:
  568. $image = imagecreatefrompng($bigImg);
  569. $color = imagecolorallocate($image, 255, 255, 255);
  570. imagecolortransparent($image, $color);
  571. imagefill($image, 0, 0, $color);
  572. break;
  573. default:
  574. $image = imagecreatefromjpeg($filename);
  575. break;
  576. }
  577. //重采样拷贝部分图像并调整大小
  578. imagecopyresampled($destImage, $image, 0, 0, 0, 0, $width, $height, $widthOrig, $heightOrig);
  579. // 将图片保存到服务器
  580. imagejpeg($destImage, $smallImg, 100);
  581. //销毁图片,释放内存
  582. imagedestroy($destImage);
  583. return true;
  584. }
  585. }
  586. /**
  587. * 缩放并按给定长宽比裁切图片
  588. * @param string $bigImg 原图路径
  589. * @param string $smallImg 缩放以后的文件路径
  590. * @param int $width 缩放宽度
  591. * @param int $height 缩放高度
  592. */
  593. public function imgCutScale($bigImg, $smallImg = 'test.jpg', $width = 90, $height = 130)
  594. {
  595. if (!file_exists($bigImg)) {
  596. $this->setError('img_cut_scale', $bigImg . "文件不存在");
  597. return;
  598. }
  599. ini_set("memory_limit", "128M");
  600. //大图文件地址,缩略宽,缩略高,小图地址
  601. $image = getimagesize($bigImg);//获取大图信息
  602. switch ($image[2]) {//判断图像类型
  603. case 1:
  604. $im = imagecreatefromgif($bigImg);
  605. break;
  606. case 2:
  607. $im = imagecreatefromjpeg($bigImg);
  608. break;
  609. case 3:
  610. $im = imagecreatefrompng($bigImg);
  611. $color = imagecolorallocate($im, 255, 255, 255);
  612. imagecolortransparent($im, $color);
  613. imagefill($im, 0, 0, $color);
  614. break;
  615. }
  616. $src_W = imagesx($im);//获取大图宽
  617. $src_H = imagesy($im);//获取大图高
  618. //计算比例
  619. //检查图片高度和宽度
  620. $srcScale = sprintf("%.2f", ($src_W / $src_H));//原图比例
  621. $destScale = sprintf("%.2f", ($width / $height));//缩略图比例
  622. //echo "<p>原始比例:".$srcScale.";目标比例".$destScale."</p>";
  623. if ($srcScale > $destScale) {
  624. //说明高度不够,就以高度为准
  625. $myH = $src_H;
  626. $myW = intval($src_H * ($width / $height));
  627. //获取开始位置
  628. $myY = 0;
  629. $myX = intval(($src_W - $myW) / 2);
  630. } elseif ($srcScale < $destScale) {
  631. //宽度不够就以宽度为准
  632. $myW = $src_W;
  633. $myH = intval($src_W * ($height / $width));
  634. $myX = 0;
  635. $myY = intval(($src_H - $myH) / 2);
  636. } else {
  637. if ($src_W > $src_H) {
  638. //echo "<p>case 1:</p>";
  639. $myH = $src_H;
  640. $myW = intval($src_H * ($width / $height));
  641. //获取开始位置
  642. $myY = 0;
  643. $myX = intval(($src_W - $myW) / 2);
  644. }
  645. if ($src_W < $src_H) {
  646. //echo "case 2";
  647. $myW = $src_W;
  648. $myH = intval($src_W * ($height / $width));
  649. $myX = 0;
  650. $myY = intval(($src_H - $myH) / 2);
  651. }
  652. }
  653. if ($src_W == $src_H) {
  654. $myW = intval($src_H * ($width / $height));
  655. $myH = $src_H;
  656. $myX = intval(($src_W - $myW) / 2);
  657. $myY = 0;
  658. }
  659. //echo "<p>SW:" . $src_W ."W:" .$myW . "</p><p>X".$myX."</p><p>SH".$src_H.";H:" . $myH ."<p>Y".$myY."</p>";
  660. //从中间截取图片
  661. if ($image[2] == 3) {
  662. $tn = imagecreate($myW, $myH);//创建小图
  663. } else {
  664. $tn = imagecreatetruecolor($myW, $myH);
  665. }
  666. imagecopy($tn, $im, 0, 0, $myX, $myY, $myW, $myH);
  667. if ($image[2] == 3) {
  668. imagepng($tn, $smallImg, 9);
  669. } else {
  670. imagejpeg($tn, $smallImg, 100);//输出图像
  671. }
  672. imagedestroy($im);
  673. }
  674. /**
  675. *
  676. * 剪切圖片到指定大小
  677. * @param String $bigImg 原始圖片
  678. * @param Int $width 寬
  679. * @param Int $height高
  680. * @param String $smallImg 縮放後保存的圖片
  681. */
  682. public function imgCutSmall($bigImg, $smallImg, $width, $height)
  683. {
  684. if (!file_exists($bigImg)) {
  685. return;
  686. }
  687. ini_set("memory_limit", "128M");
  688. //大图文件地址,缩略宽,缩略高,小图地址
  689. $imgage = getimagesize($bigImg);//获取大图信息
  690. switch ($imgage[2]) {//判断图像类型
  691. case 1:
  692. $im = imagecreatefromgif($bigImg);
  693. break;
  694. case 2:
  695. $im = imagecreatefromjpeg($bigImg);
  696. break;
  697. case 3:
  698. $im = imagecreatefrompng($bigImg);
  699. break;
  700. }
  701. $src_W = imagesx($im);//获取大图宽
  702. $src_H = imagesy($im);//获取大图高
  703. if ($image[2] == 3) {
  704. $tn = imagecrate($width, $height);//创建小图
  705. } else {
  706. $tn = imagecreatetruecolor($width, $height);
  707. }
  708. imagecopy($tn, $im, 0, 0, 0, 0, $width, $height);
  709. if ($image[2] == 3) {
  710. imagepng($tn, $smallImg, 9);
  711. } else {
  712. imagejpeg($tn, $smallImg, 100);//输出图像
  713. }
  714. imagedestroy($im);
  715. }
  716. /**
  717. * 按比例缩放图片并限制图片的最大宽度或高度
  718. * @param string $bigImg 原图地址
  719. * @param string $smallImg 缩略图地址
  720. * @param int $maxValue 最大宽高
  721. */
  722. public function imgResizeMaxSize($bigImg, $smallImg, $maxValue = 392)
  723. {
  724. // 图片路径
  725. if (!file_exists($bigImg)) {
  726. $this->setError('img_resize_samll', $bigImg . "文件不存在");
  727. return false;
  728. } else {
  729. ini_set("memory_limit", "128M");
  730. $filename = $bigImg;
  731. // 获取原图片的尺寸
  732. list($widthOrig, $heightOrig) = getimagesize($filename);
  733. $width = $widthOrig;
  734. $height = $heightOrig;
  735. //根据比例,计算新图片的尺寸
  736. if ($widthOrig > $heightOrig) {
  737. if ($widthOrig > $maxValue) {
  738. $width = $maxValue;
  739. $height = ($maxValue / $widthOrig) * $heightOrig;
  740. }
  741. } else {
  742. if ($heightOrig > $maxValue) {
  743. $height = $maxValue;
  744. $width = ($maxValue / $heightOrig) * $widthOrig;
  745. }
  746. }
  747. //$height = ($width / $widthOrig) * $heightOrig;
  748. //新建一个真彩色图像
  749. $destImage = imagecreate($width, $height);
  750. //从 JPEG 文件或 URL 新建一图像
  751. $imageInfo = getimagesize($bigImg);//获取大图信息
  752. switch ($imageInfo[2]) {//判断图像类型
  753. case 1:
  754. $image = imagecreatefromgif($bigImg);
  755. break;
  756. case 2:
  757. $image = imagecreatefromjpeg($bigImg);
  758. break;
  759. case 3:
  760. $image = imagecreatefrompng($bigImg);
  761. $color = imagecolorallocate($image, 255, 255, 255);
  762. imagecolortransparent($image, $color);
  763. imagefill($image, 0, 0, $color);
  764. break;
  765. default:
  766. $image = imagecreatefromjpeg($filename);
  767. break;
  768. }
  769. //重采样拷贝部分图像并调整大小
  770. imagecopyresampled($destImage, $image, 0, 0, 0, 0, $width, $height, $widthOrig, $heightOrig);
  771. // 将图片保存到服务器
  772. imagejpeg($destImage, $smallImg, 100);
  773. //销毁图片,释放内存
  774. imagedestroy($destImage);
  775. return true;
  776. }
  777. }
  778. }