Core.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. <?php
  2. namespace Upload\Src\Store;
  3. use Dever;
  4. use Dever\String\Helper as Helper;
  5. use Dever\Loader\Config;
  6. class Core
  7. {
  8. protected $data;
  9. protected $config;
  10. protected $handle;
  11. protected $img;
  12. protected $output;
  13. protected $limit;
  14. protected $name;
  15. protected $path;
  16. protected $ext = '';
  17. protected $file;
  18. protected $size;
  19. protected $base = '';
  20. /**
  21. * __construct
  22. *
  23. * @return mixed
  24. */
  25. public function __construct($data = array())
  26. {
  27. $this->data = $data;
  28. }
  29. /**
  30. * 获取根目录
  31. *
  32. * @return mixed
  33. */
  34. protected function root()
  35. {
  36. if (!$this->base) {
  37. $path = Config::data();
  38. $this->base = Dever::path($path . 'upload/');
  39. }
  40. return $this->base;
  41. }
  42. /**
  43. * 验证数据
  44. *
  45. * @return mixed
  46. */
  47. private function check($param)
  48. {
  49. foreach ($param as $k => $v) {
  50. $method = 'check_' . $v;
  51. $this->$method();
  52. if ($this->output['status'] == -1) {
  53. break;
  54. }
  55. }
  56. }
  57. /**
  58. * 验证key是否包含有后续处理的方法
  59. *
  60. * @return mixed
  61. */
  62. private function check_handle()
  63. {
  64. if (isset($this->data['key']) && strpos($this->data['key'], '_') !== false) {
  65. $temp = explode('_', $this->data['key']);
  66. $this->data['key'] = $temp[0];
  67. unset($temp[0]);
  68. foreach ($temp as $k => $v) {
  69. $this->handle[] = explode('=', $v);
  70. }
  71. }
  72. }
  73. /**
  74. * 验证文件是否存在
  75. *
  76. * @return mixed
  77. */
  78. private function check_file()
  79. {
  80. if ($this->data['file']['tmp_name'] == '') {
  81. $this->output['status'] = -1;
  82. $this->output['message'] = '没有选择文件';
  83. }
  84. }
  85. /**
  86. * 验证基本配置
  87. *
  88. * @return mixed
  89. */
  90. private function check_key()
  91. {
  92. if (trim($this->data['key']) == '') {
  93. $this->output['status'] = -1;
  94. $this->output['message'] = '请添加配置key';
  95. } else {
  96. $this->config = Dever::load('upload/upload-one', $this->data['key']);
  97. if (!$this->config) {
  98. $this->output['status'] = -1;
  99. $this->output['message'] = '此配置不存在';
  100. }
  101. }
  102. }
  103. /**
  104. * 验证文件类型
  105. *
  106. * @return mixed
  107. */
  108. private function check_type()
  109. {
  110. if (!$this->ext) {
  111. $ext = $this->getExt($this->data['file']['tmp_name']);
  112. if (strpos($this->config['type'], $ext) === false) {
  113. $this->output['status'] = -1;
  114. $this->output['message'] = '文件格式不符合要求';
  115. }
  116. $this->ext = '.' . $ext;
  117. }
  118. }
  119. /**
  120. * 验证文件大小
  121. *
  122. * @return mixed
  123. */
  124. private function check_size()
  125. {
  126. if ($this->config['width'] > 0 || $this->config['height'] > 0) {
  127. $this->limit = getimagesize($this->data['file']['tmp_name']);
  128. }
  129. # 默认30M
  130. $size = $this->config['size'] > 0 ? 1024*$this->config['size'] : 30*1024*1024;
  131. $this->size = $this->data['file']['size'];
  132. if (($size < $this->data['file']['size']) && $size > 0) {
  133. $this->output['status'] = -1;
  134. $this->output['message'] = '文件不能超过'.$size.'k';
  135. } elseif ($this->config['width'] > 0 && $this->config['width'] < $this->limit[0]) {
  136. $this->output['status'] = -1;
  137. $this->output['message'] = '图片宽度不能超过' . $this->config['width'] . 'px';
  138. } elseif ($this->config['height'] > 0 && $this->config['height'] < $this->limit[1]) {
  139. $this->output['status'] = -1;
  140. $this->output['message'] = '图片高度不能超过' . $this->config['height'] . 'px';
  141. }
  142. }
  143. /**
  144. * 上传操作
  145. *
  146. * @return mixed
  147. */
  148. public function copy()
  149. {
  150. $this->output['status'] = 1;
  151. if (is_string($this->data['file'])) {
  152. /*
  153. if (strpos($this->data['file'], 'http') !== false) {
  154. $this->output['status'] = -1;
  155. $this->output['message'] = '暂时不支持复制网络文件';
  156. return $this->output;
  157. }
  158. */
  159. $this->root();
  160. header('Content-type: text/json; charset=utf-8');
  161. $path = Dever::path($this->base, 'tmp/');
  162. $name = urldecode($this->data['file']);
  163. $this->data['file'] = array();
  164. $this->data['file']['name'] = 'Tmp' . sha1($name);
  165. //$this->data['file']['name'] = 'Tmp' . Helper::rand(8) . md5(microtime() . rand(0,1000)) . '.jpg';
  166. $this->data['file']['tmp_name'] = $path . $this->data['file']['name'];
  167. if (!is_file($this->data['file']['tmp_name'])) {
  168. $file = Dever::curl($name);
  169. if (stristr($file, 'webp')) {
  170. $this->ext = '.jpg';
  171. }
  172. file_put_contents($this->data['file']['tmp_name'], $file);
  173. }
  174. $this->data['file']['size'] = filesize($this->data['file']['tmp_name']);
  175. } else {
  176. header("Content-type: application/json; charset=utf-8");
  177. }
  178. $this->check(array('handle', 'file', 'key', 'type', 'size'));
  179. if ($this->output['status'] == -1) {
  180. $this->delete();
  181. return $this->output;
  182. }
  183. $this->save();
  184. if ($this->output['status'] == -1) {
  185. return $this->output;
  186. }
  187. if (isset($this->handle) && is_array($this->handle)) {
  188. foreach ($this->handle as $k => $v) {
  189. $method = 'handle_' . $v[0];
  190. if (method_exists($this, $method)) {
  191. $this->$method($v);
  192. }
  193. $this->$method($v[1]);
  194. }
  195. } elseif (isset($this->config['alter']) && $this->config['alter']) {
  196. parse_str($this->config['alter'], $handle);
  197. if ($handle) {
  198. foreach ($handle as $k => $v) {
  199. $method = 'handle_' . $k;
  200. if (method_exists($this, $method)) {
  201. $this->$method($v);
  202. }
  203. }
  204. }
  205. }
  206. $this->output['status'] = 1;
  207. $this->output['name'] = $this->data['file']['name'];
  208. return $this->output;
  209. }
  210. protected function update($id)
  211. {
  212. $param['set_name'] = $this->name;
  213. $param['set_source_name'] = $this->data['file']['name'];
  214. $param['set_file'] = $this->file;
  215. $param['set_key'] = md5($this->output['url']);
  216. $param['set_ext'] = $this->ext;
  217. if ($this->limit) {
  218. $param['set_width'] = $this->limit[0];
  219. $param['set_height'] = $this->limit[1];
  220. }
  221. if ($this->size) {
  222. $param['set_size'] = $this->size;
  223. }
  224. $param['where_id'] = $id;
  225. Dever::load('upload/file-update', $param);
  226. }
  227. protected function insert()
  228. {
  229. $param['add_name'] = $this->name;
  230. $param['add_source_name'] = $this->data['file']['name'];
  231. $param['add_file'] = $this->file;
  232. $param['add_key'] = md5($this->output['url']);
  233. $param['add_ext'] = $this->ext;
  234. $param['add_upload'] = $this->data['key'];
  235. if ($this->limit) {
  236. $param['add_width'] = $this->limit[0];
  237. $param['add_height'] = $this->limit[1];
  238. }
  239. if ($this->size) {
  240. $param['add_size'] = $this->size;
  241. }
  242. $param['add_state'] = 1;
  243. //file_put_contents(DEVER_PATH . 'data/test', var_export($param,true));
  244. Dever::load('upload/file-insert', $param);
  245. }
  246. /**
  247. * getExt
  248. *
  249. * @return mixed
  250. */
  251. protected function getExt($filename)
  252. {
  253. if (isset($this->data['file']['type'])) {
  254. $ext = $this->getExtByMine($this->data['file']['type']);
  255. } elseif (function_exists('finfo_open')) {
  256. $finfo = finfo_open(FILEINFO_MIME); // 返回 mime 类型
  257. $code = finfo_file($finfo, $filename);
  258. finfo_close($finfo);
  259. $temp = explode(';', $code);
  260. $ext = $this->getExtByMine($temp[0]);
  261. } else {
  262. $ext = $this->getExtByByte($filename);
  263. }
  264. if (!$ext || $ext == 'txt' || $ext == 'exe') {
  265. if (isset($this->data['file']['type'])) {
  266. $ext = $this->getExtByMine($this->data['file']['type']);
  267. }
  268. if (!$ext || $ext == 'txt' || $ext == 'exe') {
  269. $ext = $this->getExtByByte($filename);
  270. }
  271. }
  272. return $ext;
  273. }
  274. public function delete()
  275. {
  276. @unlink($this->data['file']['tmp_name']);
  277. }
  278. /**
  279. * 根据mime类型获取文件扩展名
  280. *
  281. * @return mixed
  282. */
  283. protected function getExtByMine($mine)
  284. {
  285. $mine = trim($mine);
  286. $config = array
  287. (
  288. 'application/envoy' => 'evy',
  289. 'application/fractals' => 'fif',
  290. 'application/futuresplash' => 'spl',
  291. 'application/hta' => 'hta',
  292. 'application/internet-property-stream' => 'acx',
  293. 'application/mac-binhex40' => 'hqx',
  294. 'application/msword' => 'doc',
  295. 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
  296. 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
  297. 'video/x-m4v' => 'mp4',
  298. 'video/mp4' => 'mp4',
  299. 'application/octet-stream' => 'exe',
  300. 'application/oda' => 'oda',
  301. 'application/olescript' => 'axs',
  302. 'application/pdf' => 'pdf',
  303. 'application/pics-rules' => 'prf',
  304. 'application/pkcs10' => 'p10',
  305. 'application/pkix-crl' => 'crl',
  306. 'application/postscript' => 'ai',
  307. 'application/postscript' => 'eps',
  308. 'application/postscript' => 'ps',
  309. 'application/rtf' => 'rtf',
  310. 'application/set-payment-initiation' => 'setpay',
  311. 'application/set-registration-initiation' => 'setreg',
  312. 'application/vnd.ms-excel' => 'xls',
  313. 'application/vnd.ms-outlook' => 'msg',
  314. 'application/vnd.ms-pkicertstore' => 'sst',
  315. 'application/vnd.ms-pkiseccat' => 'cat',
  316. 'application/vnd.ms-pkistl' => 'stl',
  317. 'application/vnd.ms-powerpoint' => 'ppt',
  318. 'application/vnd.ms-project' => 'mpp',
  319. 'application/vnd.ms-works' => 'wps',
  320. 'application/winhlp' => 'hlp',
  321. 'application/x-bcpio' => 'bcpio',
  322. 'application/x-cdf' => 'cdf',
  323. 'application/x-compress' => 'z',
  324. 'application/x-compressed' => 'tgz',
  325. 'application/x-cpio' => 'cpio',
  326. 'application/x-csh' => 'csh',
  327. 'application/x-director' => 'dir',
  328. 'application/x-dvi' => 'dvi',
  329. 'application/x-gtar' => 'gtar',
  330. 'application/x-gzip' => 'gz',
  331. 'application/x-hdf' => 'hdf',
  332. 'application/x-internet-signup' => 'isp',
  333. 'application/x-iphone' => 'iii',
  334. 'application/x-javascript' => 'js',
  335. 'application/x-latex' => 'latex',
  336. 'application/x-msaccess' => 'mdb',
  337. 'application/x-mscardfile' => 'crd',
  338. 'application/x-msclip' => 'clp',
  339. 'application/x-msdownload' => 'dll',
  340. 'application/x-msmediaview' => 'mvb',
  341. 'application/x-msmetafile' => 'wmf',
  342. 'application/x-msmoney' => 'mny',
  343. 'application/x-mspublisher' => 'pub',
  344. 'application/x-msschedule' => 'scd',
  345. 'application/x-msterminal' => 'trm',
  346. 'application/x-mswrite' => 'wri',
  347. 'application/x-netcdf' => 'cdf',
  348. 'application/x-netcdf' => 'nc',
  349. 'application/x-perfmon' => 'pma',
  350. 'application/x-pkcs12' => 'p12',
  351. 'application/x-pkcs12' => 'pfx',
  352. 'application/x-pkcs7-certificates' => 'p7b',
  353. 'application/x-pkcs7-certreqresp' => 'p7r',
  354. 'application/x-pkcs7-mime' => 'p7c',
  355. 'application/x-pkcs7-signature' => 'p7s',
  356. 'application/x-sh' => 'sh',
  357. 'application/x-shar' => 'shar',
  358. 'application/x-shockwave-flash' => 'swf',
  359. 'application/x-stuffit' => 'sit',
  360. 'application/x-sv4cpio' => 'sv4cpio',
  361. 'application/x-sv4crc' => 'sv4crc',
  362. 'application/x-tar' => 'tar',
  363. 'application/x-tcl' => 'tcl',
  364. 'application/x-tex' => 'tex',
  365. 'application/x-texinfo' => 'texi',
  366. 'application/x-texinfo' => 'texinfo',
  367. 'application/x-troff' => 'roff',
  368. 'application/x-troff' => 't',
  369. 'application/x-troff' => 'tr',
  370. 'application/x-troff-man' => 'man',
  371. 'application/x-troff-me' => 'me',
  372. 'application/x-troff-ms' => 'ms',
  373. 'application/x-ustar' => 'ustar',
  374. 'application/x-wais-source' => 'src',
  375. 'application/x-x509-ca-cert' => 'cer',
  376. 'application/ynd.ms-pkipko' => 'pko',
  377. 'application/zip' => 'zip',
  378. 'audio/basic' => 'au',
  379. 'audio/basic' => 'snd',
  380. 'audio/mid' => 'mid',
  381. 'audio/mid' => 'rmi',
  382. 'audio/mpeg' => 'mp3',
  383. 'audio/mp3' => 'mp3',
  384. 'audio/x-aiff' => 'aif',
  385. 'audio/x-aiff' => 'aifc',
  386. 'audio/x-aiff' => 'aiff',
  387. 'audio/x-mpegurl' => 'm3u',
  388. 'audio/x-pn-realaudio' => 'ram',
  389. 'audio/x-wav' => 'wav',
  390. 'image/bmp' => 'bmp',
  391. 'image/cis-cod' => 'cod',
  392. 'image/gif' => 'gif',
  393. 'image/ief' => 'ief',
  394. 'image/jpeg' => 'jpg',
  395. 'image/pipeg' => 'jfif',
  396. 'image/svg+xml' => 'svg',
  397. 'image/tiff' => 'tif',
  398. 'image/tiff' => 'tiff',
  399. 'image/x-cmu-raster' => 'ras',
  400. 'image/x-cmx' => 'cmx',
  401. 'image/x-icon' => 'ico',
  402. 'image/x-portable-anymap' => 'pnm',
  403. 'image/x-portable-bitmap' => 'pbm',
  404. 'image/x-portable-graymap' => 'pgm',
  405. 'image/x-portable-pixmap' => 'ppm',
  406. 'image/x-rgb' => 'rgb',
  407. 'image/x-xbitmap' => 'xbm',
  408. 'image/x-xpixmap' => 'xpm',
  409. 'image/x-xwindowdump' => 'xwd',
  410. 'message/rfc822' => 'mht',
  411. 'message/rfc822' => 'mhtml',
  412. 'message/rfc822' => 'nws',
  413. 'text/css' => 'css',
  414. 'text/h323' => '323',
  415. 'text/html' => 'html',
  416. 'text/iuls' => 'uls',
  417. 'text/plain' => 'txt',
  418. 'text/richtext' => 'rtx',
  419. 'text/scriptlet' => 'sct',
  420. 'text/tab-separated-values' => 'tsv',
  421. 'text/webviewhtml' => 'htt',
  422. 'text/x-component' => 'htc',
  423. 'text/x-setext' => 'etx',
  424. 'text/x-vcard' => 'vcf',
  425. 'video/mpeg' => 'mpeg',
  426. 'video/quicktime' => 'mov',
  427. 'video/x-ms-asf' => 'asx',
  428. 'video/x-msvideo' => 'avi',
  429. 'video/x-sgi-movie' => 'movie',
  430. 'x-world/x-vrml' => 'flr',
  431. 'application/x-rar' => 'rar',
  432. );
  433. if (isset($config[$mine])) {
  434. return $config[$mine];
  435. } else {
  436. return false;
  437. }
  438. }
  439. /**
  440. * getExt
  441. *
  442. * @return mixed
  443. */
  444. protected function getExtByByte($filename)
  445. {
  446. $file = fopen($filename,"rb");
  447. $bin = fread($file,2);
  448. fclose($file);
  449. $strInfo = @unpack("c2chars",$bin);
  450. $typeCode = intval($strInfo['chars1'].$strInfo['chars2']);
  451. $fileType = '';
  452. switch ($typeCode) {
  453. case 7790:
  454. $fileType = 'exe';
  455. break;
  456. case 7784:
  457. $fileType = 'midi';
  458. break;
  459. case 8297:
  460. $fileType = 'rar';
  461. break;
  462. case 255216:
  463. $fileType = 'jpg';
  464. break;
  465. case 7173:
  466. $fileType = 'gif';
  467. break;
  468. case 13780:
  469. $fileType = 'png';
  470. break;
  471. case 6677:
  472. $fileType = 'bmp';
  473. break;
  474. case 6787:
  475. $fileType = 'swf';
  476. break;
  477. case 6063;
  478. $fileType = 'php|xml';
  479. break;
  480. case 6033:
  481. $fileType = 'html|htm|shtml';
  482. break;
  483. case 8075:
  484. $fileType = 'zip';
  485. break;
  486. case 6782:
  487. case 1310:
  488. $fileType = 'txt';
  489. break;
  490. case 4742:
  491. $fileType = 'js';
  492. break;
  493. case 8273:
  494. $fileType = 'wav';
  495. break;
  496. case 7368:
  497. $fileType = 'mp3';
  498. break;
  499. case 3780:
  500. $fileType = 'pdf';
  501. break;
  502. default:
  503. $fileType = 'unknown'.$typeCode;
  504. break;
  505. }
  506. if ($strInfo['chars1'] == '-1' && $strInfo['chars2'] == '-40') {
  507. return 'jpg';
  508. }
  509. if ($strInfo['chars1'] == '-119' && $strInfo['chars2'] == '80') {
  510. return 'png';
  511. }
  512. if ($strInfo['chars1'] == '-48' && $strInfo['chars2'] == '-49') {
  513. return 'msi';
  514. }
  515. return $fileType;
  516. }
  517. }