PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/function/file.function.php

https://gitlab.com/imxieke/XCloud
PHP | 818 lines | 687 code | 30 blank | 101 comment | 62 complexity | e424263888e052b49f5a2b81e4149a26 MD5 | raw file
  1. <?php
  2. /*
  3. * @link http://www.kalcaddle.com/
  4. * @author warlee | e-mail:kalcaddle@qq.com
  5. * @copyright warlee 2014.(Shanghai)Co.,Ltd
  6. * @license http://kalcaddle.com/tools/licenses/license.txt
  7. */
  8. /**
  9. * 系统函数: filesize(),file_exists(),pathinfo(),rname(),unlink(),filemtime(),is_readable(),is_wrieteable();
  10. * 获取文件详细信息 file_info($file_name)
  11. * 获取文件夹详细信息 path_info($dir)
  12. * 递归获取文件夹信息 path_info_more($dir,&$file_num=0,&$path_num=0,&$size=0)
  13. * 获取文件夹下文件列表 path_list($dir)
  14. * 路径当前文件[夹]名 get_path_this($path)
  15. * 获取路径父目录 get_path_father($path)
  16. * 删除文件 del_file($file)
  17. * 递归删除文件夹 del_dir($dir)
  18. * 递归复制文件夹 copy_dir($source, $dest)
  19. * 创建目录 mk_dir($dir, $mode = 0777)
  20. * 文件大小格式化 size_format($bytes, $precision = 2)
  21. * 判断是否绝对路径 path_is_absolute( $path )
  22. * 扩展名的文件类型 ext_type($ext)
  23. * 文件下载 file_download($file)
  24. * 文件下载到服务器 file_download_this($from, $file_name)
  25. * 获取文件(夹)权限 get_mode($file) //rwx_rwx_rwx [文件名需要系统编码]
  26. * 上传文件(单个,多个) upload($fileInput, $path = './');//
  27. * 获取配置文件项 get_config($file, $ini, $type="string")
  28. * 修改配置文件项 update_config($file, $ini, $value,$type="string")
  29. * 写日志到LOG_PATH下 write_log('dd','default|.自建目录.','log|error|warning|debug|info|db')
  30. */
  31. // 传入参数为程序编码时,有传出,则用程序编码,
  32. // 传入参数没有和输出无关时,则传入时处理成系统编码。
  33. function iconv_app($str){
  34. global $config;
  35. $result = iconv($config['system_charset'], $config['app_charset'], $str);
  36. if (strlen($result)==0) {
  37. $result = $str;
  38. }
  39. return $result;
  40. }
  41. function iconv_system($str){
  42. global $config;
  43. $result = iconv($config['app_charset'], $config['system_charset'], $str);
  44. if (strlen($result)==0) {
  45. $result = $str;
  46. }
  47. return $result;
  48. }
  49. function get_filesize($path){
  50. @$ret = abs(sprintf("%u",filesize($path)));
  51. return (int)$ret;
  52. }
  53. /**
  54. * 获取文件详细信息
  55. * 文件名从程序编码转换成系统编码,传入utf8,系统函数需要为gbk
  56. */
  57. function file_info($path){
  58. $name = get_path_this($path);
  59. $size = get_filesize($path);
  60. $info = array(
  61. 'name' => iconv_app($name),
  62. 'path' => iconv_app(get_path_father($path)),
  63. 'ext' => get_path_ext($path),
  64. 'type' => 'file',
  65. 'mode' => get_mode($path),
  66. 'atime' => fileatime($path), //最后访问时间
  67. 'ctime' => filectime($path), //创建时间
  68. 'mtime' => filemtime($path), //最后修改时间
  69. 'is_readable' => intval(is_readable($path)),
  70. 'is_writeable' => intval(is_writeable($path)),
  71. 'size' => $size,
  72. 'size_friendly' => size_format($size, 2)
  73. );
  74. return $info;
  75. }
  76. /**
  77. * 获取文件夹细信息
  78. */
  79. function folder_info($path){
  80. $info = array(
  81. 'name' => iconv_app(get_path_this($path)),
  82. 'path' => iconv_app(get_path_father($path)),
  83. 'type' => 'folder',
  84. 'mode' => get_mode($path),
  85. 'atime' => fileatime($path), //访问时间
  86. 'ctime' => filectime($path), //创建时间
  87. 'mtime' => filemtime($path), //最后修改时间
  88. 'is_readable' => intval(is_readable($path)),
  89. 'is_writeable' => intval(is_writeable($path))
  90. );
  91. return $info;
  92. }
  93. /**
  94. * 获取一个路径(文件夹&文件) 当前文件[夹]名
  95. * test/11/ ==>11 test/1.c ==>1.c
  96. */
  97. function get_path_this($path){
  98. $path = str_replace('\\','/', rtrim(trim($path),'/'));
  99. return substr($path,strrpos($path,'/')+1);
  100. }
  101. /**
  102. * 获取一个路径(文件夹&文件) 父目录
  103. * /test/11/==>/test/ /test/1.c ==>/www/test/
  104. */
  105. function get_path_father($path){
  106. $path = str_replace('\\','/', rtrim(trim($path),'/'));
  107. return substr($path, 0, strrpos($path,'/')+1);
  108. }
  109. /**
  110. * 获取扩展名
  111. */
  112. function get_path_ext($path){
  113. $name = get_path_this($path);
  114. $ext = '';
  115. if(strstr($name,'.')){
  116. $ext = substr($name,strrpos($name,'.')+1);
  117. $ext = strtolower($ext);
  118. }
  119. if (strlen($ext)>3 && preg_match("/([\x81-\xfe][\x40-\xfe])/", $ext, $match)) {
  120. $ext = '';
  121. }
  122. return $ext;
  123. }
  124. //自动获取不重复文件(夹)名
  125. //如果传入$file_add 则检测存在则自定重命名 a.txt 为a{$file_add}.txt
  126. function get_filename_auto($path,$file_add = "",$same_file_type=''){
  127. if (is_dir($path)) {//文件夹则忽略
  128. return $path;
  129. }
  130. //重名处理方式;replace,skip,filename_auto
  131. if ($same_file_type == '') {
  132. $same_file_type = 'replace';
  133. }
  134. //重名处理
  135. if (file_exists($path)) {
  136. if ($same_file_type=='replace') {
  137. return $path;
  138. }else if($same_file_type=='skip'){
  139. return false;
  140. }
  141. }
  142. $i=1;
  143. $father = get_path_father($path);
  144. $name = get_path_this($path);
  145. $ext = get_path_ext($name);
  146. if (strlen($ext)>0) {
  147. $ext='.'.$ext;
  148. $name = substr($name,0,strlen($name)-strlen($ext));
  149. }
  150. while(file_exists($path)){
  151. if ($file_add != '') {
  152. $path = $father.$name.$file_add.$ext;
  153. $file_add.='-';
  154. }else{
  155. $path = $father.$name.'('.$i.')'.$ext;
  156. $i++;
  157. }
  158. }
  159. return $path;
  160. }
  161. /**
  162. * 判断文件夹是否可写
  163. */
  164. function path_writable($path) {
  165. $file = $path.'/test'.time().'.txt';
  166. $dir = $path.'/test'.time();
  167. if(@is_writable($path) && @touch($file) && @unlink($file)) return true;
  168. if(@mkdir($dir,0777) && @rmdir($dir)) return true;
  169. return false;
  170. }
  171. /**
  172. * 获取文件夹详细信息,文件夹属性时调用,包含子文件夹数量,文件数量,总大小
  173. */
  174. function path_info($path){
  175. //if (!is_dir($path)) return false;
  176. $pathinfo = _path_info_more($path);//子目录文件大小统计信息
  177. $folderinfo = folder_info($path);
  178. return array_merge($pathinfo,$folderinfo);
  179. }
  180. /**
  181. * 检查名称是否合法
  182. */
  183. function path_check($path){
  184. $check = array('/','\\',':','*','?','"','<','>','|');
  185. $path = rtrim($path,'/');
  186. $path = get_path_this($path);
  187. foreach ($check as $v) {
  188. if (strstr($path,$v)) {
  189. return false;
  190. }
  191. }
  192. return true;
  193. }
  194. /**
  195. * 递归获取文件夹信息: 子文件夹数量,文件数量,总大小
  196. */
  197. function _path_info_more($dir, &$file_num = 0, &$path_num = 0, &$size = 0){
  198. if (!$dh = opendir($dir)) return false;
  199. while (($file = readdir($dh)) !== false) {
  200. if ($file != "." && $file != "..") {
  201. $fullpath = $dir . "/" . $file;
  202. if (!is_dir($fullpath)) {
  203. $file_num ++;
  204. $size += get_filesize($fullpath);
  205. } else {
  206. _path_info_more($fullpath, $file_num, $path_num, $size);
  207. $path_num ++;
  208. }
  209. }
  210. }
  211. closedir($dh);
  212. $pathinfo['file_num'] = $file_num;
  213. $pathinfo['folder_num'] = $path_num;
  214. $pathinfo['size'] = $size;
  215. $pathinfo['size_friendly'] = size_format($size);
  216. return $pathinfo;
  217. }
  218. /**
  219. * 获取多选文件信息,包含子文件夹数量,文件数量,总大小,父目录权限
  220. */
  221. function path_info_muti($list,$time_type){
  222. if (count($list) == 1) {
  223. if ($list[0]['type']=="folder"){
  224. return path_info($list[0]['path'],$time_type);
  225. }else{
  226. return file_info($list[0]['path'],$time_type);
  227. }
  228. }
  229. $pathinfo = array(
  230. 'file_num' => 0,
  231. 'folder_num' => 0,
  232. 'size' => 0,
  233. 'size_friendly' => '',
  234. 'father_name' => '',
  235. 'mod' => ''
  236. );
  237. foreach ($list as $val){
  238. if ($val['type'] == 'folder') {
  239. $pathinfo['folder_num'] ++;
  240. $temp = path_info($val['path']);
  241. $pathinfo['folder_num'] += $temp['folder_num'];
  242. $pathinfo['file_num'] += $temp['file_num'];
  243. $pathinfo['size'] += $temp['size'];
  244. }else{
  245. $pathinfo['file_num']++;
  246. $pathinfo['size'] += get_filesize($val['path']);
  247. }
  248. }
  249. $pathinfo['size_friendly'] = size_format($pathinfo['size']);
  250. $father_name = get_path_father($list[0]['path']);
  251. $pathinfo['mode'] = get_mode($father_name);
  252. return $pathinfo;
  253. }
  254. /**
  255. * 获取文件夹下列表信息
  256. * dir 包含结尾/ d:/wwwroot/test/
  257. * 传入需要读取的文件夹路径,为程序编码
  258. */
  259. function path_list($dir,$list_file=true,$check_children=false){
  260. $dir = rtrim($dir,'/').'/';
  261. if (!is_dir($dir) || !($dh = opendir($dir))){
  262. return array('folderlist'=>array(),'filelist'=>array());
  263. }
  264. $folderlist = array();$filelist = array();//文件夹与文件
  265. while (($file = readdir($dh)) !== false) {
  266. if ($file != "." && $file != ".." && $file != ".svn" ) {
  267. $fullpath = $dir . $file;
  268. if (is_dir($fullpath)) {
  269. $info = folder_info($fullpath);
  270. if($check_children){
  271. $info['isParent'] = path_haschildren($fullpath,$list_file);
  272. }
  273. $folderlist[] = $info;
  274. } else if($list_file) {//是否列出文件
  275. $info = file_info($fullpath);
  276. if($check_children) $info['isParent'] = false;
  277. $filelist[] = $info;
  278. }
  279. }
  280. }
  281. closedir($dh);
  282. return array('folderlist' => $folderlist,'filelist' => $filelist);
  283. }
  284. // 判断文件夹是否含有子内容【区分为文件或者只筛选文件夹才算】
  285. function path_haschildren($dir,$check_file=false){
  286. $dir = rtrim($dir,'/').'/';
  287. if (!$dh = @opendir($dir)) return false;
  288. while (($file = readdir($dh)) !== false){
  289. if ($file != "." && $file != "..") {
  290. $fullpath = $dir.$file;
  291. if ($check_file) {//有子目录或者文件都说明有子内容
  292. if(is_file($fullpath) || is_dir($fullpath.'/')){
  293. return true;
  294. }
  295. }else{//只检查有没有文件
  296. @$ret =(is_dir($fullpath.'/'));
  297. return (bool)$ret;
  298. }
  299. }
  300. }
  301. closedir($dh);
  302. return false;
  303. }
  304. /**
  305. * 删除文件 传入参数编码为操作系统编码. win--gbk
  306. */
  307. function del_file($fullpath){
  308. if (!@unlink($fullpath)) { // 删除不了,尝试修改文件权限
  309. @chmod($fullpath, 0777);
  310. if (!@unlink($fullpath)) {
  311. return false;
  312. }
  313. } else {
  314. return true;
  315. }
  316. }
  317. /**
  318. * 删除文件夹 传入参数编码为操作系统编码. win--gbk
  319. */
  320. function del_dir($dir){
  321. if (!$dh = opendir($dir)) return false;
  322. while (($file = readdir($dh)) !== false) {
  323. if ($file != "." && $file != "..") {
  324. $fullpath = $dir . '/' . $file;
  325. if (!is_dir($fullpath)) {
  326. if (!unlink($fullpath)) { // 删除不了,尝试修改文件权限
  327. chmod($fullpath, 0777);
  328. if (!unlink($fullpath)) {
  329. return false;
  330. }
  331. }
  332. } else {
  333. if (!del_dir($fullpath)) {
  334. chmod($fullpath, 0777);
  335. if (!del_dir($fullpath)) return false;
  336. }
  337. }
  338. }
  339. }
  340. closedir($dh);
  341. if (rmdir($dir)) {
  342. return true;
  343. } else {
  344. return false;
  345. }
  346. }
  347. /**
  348. * 复制文件夹
  349. * eg:将D:/wwwroot/下面wordpress复制到
  350. * D:/wwwroot/www/explorer/0000/del/1/
  351. * 末尾都不需要加斜杠,复制到地址如果不加源文件夹名,
  352. * 就会将wordpress下面文件复制到D:/wwwroot/www/explorer/0000/del/1/下面
  353. * $from = 'D:/wwwroot/wordpress';
  354. * $to = 'D:/wwwroot/www/explorer/0000/del/1/wordpress';
  355. */
  356. function copy_dir($source, $dest){
  357. if (!$dest) return false;
  358. if ($source == substr($dest,0,strlen($source))) return;//防止父文件夹拷贝到子文件夹,无限递归
  359. $result = false;
  360. if (is_file($source)) {
  361. if ($dest[strlen($dest)-1] == '/') {
  362. $__dest = $dest . "/" . basename($source);
  363. } else {
  364. $__dest = $dest;
  365. }
  366. $result = copy($source, $__dest);
  367. chmod($__dest, 0777);
  368. }elseif (is_dir($source)) {
  369. if ($dest[strlen($dest)-1] == '/') {
  370. $dest = $dest . basename($source);
  371. }
  372. if (!is_dir($dest)) {
  373. mkdir($dest,0777);
  374. }
  375. if (!$dh = opendir($source)) return false;
  376. while (($file = readdir($dh)) !== false) {
  377. if ($file != "." && $file != "..") {
  378. if (!is_dir($source . "/" . $file)) {
  379. $__dest = $dest . "/" . $file;
  380. } else {
  381. $__dest = $dest . "/" . $file;
  382. }
  383. $result = copy_dir($source . "/" . $file, $__dest);
  384. }
  385. }
  386. closedir($dh);
  387. }
  388. return $result;
  389. }
  390. /**
  391. * 创建目录
  392. *
  393. * @param string $dir
  394. * @param int $mode
  395. * @return bool
  396. */
  397. function mk_dir($dir, $mode = 0777){
  398. if (is_dir($dir) || @mkdir($dir, $mode)){
  399. return true;
  400. }
  401. if (!mk_dir(dirname($dir), $mode)){
  402. return false;
  403. }
  404. return @mkdir($dir, $mode);
  405. }
  406. /*
  407. * 获取文件&文件夹列表(支持文件夹层级)
  408. * path : 文件夹 $dir ——返回的文件夹array files ——返回的文件array
  409. * $deepest 是否完整递归;$deep 递归层级
  410. */
  411. function recursion_dir($path,&$dir,&$file,$deepest=-1,$deep=0){
  412. $path = rtrim($path,'/').'/';
  413. if (!is_array($file)) $file=array();
  414. if (!is_array($dir)) $dir=array();
  415. if (!$dh = opendir($path)) return false;
  416. while(($val=readdir($dh)) !== false){
  417. if ($val=='.' || $val=='..') continue;
  418. $value = strval($path.$val);
  419. if (is_file($value)){
  420. $file[] = $value;
  421. }else if(is_dir($value)){
  422. $dir[]=$value;
  423. if ($deepest==-1 || $deep<$deepest){
  424. recursion_dir($value."/",$dir,$file,$deepest,$deep+1);
  425. }
  426. }
  427. }
  428. closedir($dh);
  429. return true;
  430. }
  431. /*
  432. * $search 为包含的字符串
  433. * is_content 表示是否搜索文件内容;默认不搜索
  434. * is_case 表示区分大小写,默认不区分
  435. */
  436. function path_search($path,$search,$is_content=false,$file_ext='',$is_case=false){
  437. $ext_arr=explode("|",$file_ext);
  438. recursion_dir($path,$dirs,$files,-1,0);
  439. $strpos = 'stripos';//是否区分大小写
  440. if ($is_case) $strpos = 'strpos';
  441. $filelist = array();
  442. $folderlist = array();
  443. foreach($files as $f){
  444. $ext = get_path_ext($f);
  445. $path_this = get_path_this($f);
  446. if ($file_ext !='' && !in_array($ext,$ext_arr)) continue;//文件类型不在用户限定内
  447. if ($strpos($path_this,$search) !== false){//搜索文件名;搜到就返回;搜不到继续
  448. $filelist[] = file_info($f);
  449. continue;
  450. }
  451. if ($is_content && is_file($f)){
  452. $fp = fopen($f, "r");
  453. $content = @fread($fp,get_filesize($f));
  454. fclose($fp);
  455. if ($strpos($content,iconv_app($search)) !== false){
  456. $filelist[] = file_info($f);
  457. }
  458. }
  459. }
  460. if ($file_ext == '') {//没限定扩展名则才搜索文件夹
  461. foreach($dirs as $f){
  462. $path_this = get_path_this($f);
  463. if ($strpos($path_this,$search) !== false){
  464. $folderlist[]= array(
  465. 'name' => iconv_app(get_path_this($f)),
  466. 'path' => iconv_app(get_path_father($f))
  467. );
  468. }
  469. }
  470. }
  471. return array('folderlist' => $folderlist,'filelist' => $filelist);
  472. }
  473. /**
  474. * 修改文件、文件夹权限
  475. * @param $path 文件(夹)目录
  476. * @return :string
  477. */
  478. function chmod_path($path,$mod){
  479. //$mod = 0777;//
  480. if (!isset($mod)) $mod = 0777;
  481. if (!is_dir($path)) return @chmod($path,$mod);
  482. if (!$dh = opendir($path)) return false;
  483. while (($file = readdir($dh)) !== false){
  484. if ($file != "." && $file != "..") {
  485. $fullpath = $path . '/' . $file;
  486. chmod($fullpath,$mod);
  487. return chmod_path($fullpath,$mod);
  488. }
  489. }
  490. closedir($dh);
  491. return chmod($path,$mod);
  492. }
  493. /**
  494. * 文件大小格式化
  495. *
  496. * @param $ :$bytes, int 文件大小
  497. * @param $ :$precision int 保留小数点
  498. * @return :string
  499. */
  500. function size_format($bytes, $precision = 2){
  501. if ($bytes == 0) return "0 B";
  502. $unit = array(
  503. 'TB' => 1099511627776, // pow( 1024, 4)
  504. 'GB' => 1073741824, // pow( 1024, 3)
  505. 'MB' => 1048576, // pow( 1024, 2)
  506. 'kB' => 1024, // pow( 1024, 1)
  507. 'B ' => 1, // pow( 1024, 0)
  508. );
  509. foreach ($unit as $un => $mag) {
  510. if (doubleval($bytes) >= $mag)
  511. return round($bytes / $mag, $precision).' '.$un;
  512. }
  513. }
  514. /**
  515. * 判断路径是不是绝对路径
  516. * 返回true('/foo/bar','c:\windows').
  517. *
  518. * @return 返回true则为绝对路径,否则为相对路径
  519. */
  520. function path_is_absolute($path){
  521. if (realpath($path) == $path)// *nux 的绝对路径 /home/my
  522. return true;
  523. if (strlen($path) == 0 || $path[0] == '.')
  524. return false;
  525. if (preg_match('#^[a-zA-Z]:\\\\#', $path))// windows 的绝对路径 c:\aaa\
  526. return true;
  527. return (bool)preg_match('#^[/\\\\]#', $path); //绝对路径 运行 / 和 \绝对路径,其他的则为相对路径
  528. }
  529. /**
  530. * 获取扩展名的文件类型
  531. *
  532. * @param $ :$ext string 扩展名
  533. * @return :string;
  534. */
  535. function ext_type($ext){
  536. $ext2type = array(
  537. 'text' => array('txt','ini','log','asc','csv','tsv','vbs','bat','cmd','inc','conf','inf'),
  538. 'code' => array('css','htm','html','php','js','c','cpp','h','java','cs','sql','xml'),
  539. 'picture' => array('jpg','jpeg','png','gif','ico','bmp','tif','tiff','dib','rle'),
  540. 'audio' => array('mp3','ogg','oga','mid','midi','ram','wav','wma','aac','ac3','aif','aiff','m3a','m4a','m4b','mka','mp1','mx3','mp2'),
  541. 'flash' => array('swf'),
  542. 'video' => array('rm','rmvb','flv','mkv','wmv','asf','avi','aiff','mp4','divx','dv','m4v','mov','mpeg','vob','mpg','mpv','ogm','ogv','qt'),
  543. 'document' => array('doc','docx','docm','dotm','odt','pages','pdf','rtf','xls','xlsx','xlsb','xlsm','ppt','pptx','pptm','odp'),
  544. 'rar_achieve' => array('rar','arj','tar','ace','gz','lzh','uue','bz2'),
  545. 'zip_achieve' => array('zip','gzip','cab','tbz','tbz2'),
  546. 'other_achieve' => array('dmg','sea','sit','sqx')
  547. );
  548. foreach ($ext2type as $type => $exts) {
  549. if (in_array($ext, $exts)) {
  550. return $type;
  551. }
  552. }
  553. }
  554. /**
  555. * 输出、文件下载
  556. * 默认以附件方式下载;$download为false时则为输出文件
  557. */
  558. function file_put_out($file,$download=false){
  559. if (!is_file($file)) show_json('not a file!');
  560. set_time_limit(0);
  561. //ob_clean();//清除之前所有输出缓冲
  562. if (!file_exists($file)) show_json('file not exists',false);
  563. if (isset($_SERVER['HTTP_RANGE']) && ($_SERVER['HTTP_RANGE'] != "") &&
  564. preg_match("/^bytes=([0-9]+)-$/i", $_SERVER['HTTP_RANGE'], $match) && ($match[1] < $fsize)) {
  565. $start = $match[1];
  566. }else{
  567. $start = 0;
  568. }
  569. $size = get_filesize($file);
  570. $mime = get_file_mime(get_path_ext($file));
  571. if ($download || strstr($mime,'application/')) {//下载或者application则设置下载头
  572. $filename = get_path_this($file);//解决在IE中下载时中文乱码问题
  573. if( preg_match('/MSIE/',$_SERVER['HTTP_USER_AGENT']) ||
  574. preg_match('/Trident/',$_SERVER['HTTP_USER_AGENT'])){
  575. if($GLOBALS['config']['system_os']!='windows'){//win主机 ie浏览器;中文文件下载urlencode问题
  576. $filename = str_replace('+','%20',urlencode($filename));
  577. }
  578. }
  579. header("Content-Type: application/octet-stream");
  580. header("Content-Disposition: attachment;filename=".$filename);
  581. }
  582. header("Cache-Control: public");
  583. header("X-Powered-By: kodExplorer.");
  584. header("Content-Type: ".$mime);
  585. if ($start > 0){
  586. header("HTTP/1.1 206 Partial Content");
  587. header("Content-Ranges: bytes".$start ."-".($size - 1)."/" .$size);
  588. header("Content-Length: ".($size - $start));
  589. }else{
  590. header("Accept-Ranges: bytes");
  591. header("Content-Length: $size");
  592. }
  593. $fp = fopen($file, "rb");
  594. fseek($fp, $start);
  595. while (!feof($fp)) {
  596. print (fread($fp, 1024 * 8)); //输出文件
  597. flush();
  598. ob_flush();
  599. }
  600. fclose($fp);
  601. }
  602. /**
  603. * 远程文件下载到服务器
  604. * 支持fopen的打开都可以;支持本地、url
  605. *
  606. */
  607. function file_download_this($from, $file_name){
  608. set_time_limit(0);
  609. $fp = @fopen ($from, "rb");
  610. if ($fp){
  611. $new_fp = @fopen ($file_name, "wb");
  612. fclose($new_fp);
  613. $download_fp = @fopen ($file_name, "wb");
  614. while(!feof($fp)){
  615. if(!file_exists($file_name)){//删除目标文件;则终止下载
  616. fclose($download_fp);
  617. return false;
  618. }
  619. fwrite($download_fp, fread($fp, 1024 * 8 ), 1024 * 8);
  620. }
  621. //下载完成,重命名临时文件到目标文件
  622. fclose($download_fp);
  623. return true;
  624. }else{
  625. return false;
  626. }
  627. }
  628. /**
  629. * 获取文件(夹)权限 rwx_rwx_rwx
  630. */
  631. function get_mode($file){
  632. $Mode = fileperms($file);
  633. $theMode = ' '.decoct($Mode);
  634. $theMode = substr($theMode,-4);
  635. $Owner = array();$Group=array();$World=array();
  636. if ($Mode &0x1000) $Type = 'p'; // FIFO pipe
  637. elseif ($Mode &0x2000) $Type = 'c'; // Character special
  638. elseif ($Mode &0x4000) $Type = 'd'; // Directory
  639. elseif ($Mode &0x6000) $Type = 'b'; // Block special
  640. elseif ($Mode &0x8000) $Type = '-'; // Regular
  641. elseif ($Mode &0xA000) $Type = 'l'; // Symbolic Link
  642. elseif ($Mode &0xC000) $Type = 's'; // Socket
  643. else $Type = 'u'; // UNKNOWN
  644. // Determine les permissions par Groupe
  645. $Owner['r'] = ($Mode &00400) ? 'r' : '-';
  646. $Owner['w'] = ($Mode &00200) ? 'w' : '-';
  647. $Owner['x'] = ($Mode &00100) ? 'x' : '-';
  648. $Group['r'] = ($Mode &00040) ? 'r' : '-';
  649. $Group['w'] = ($Mode &00020) ? 'w' : '-';
  650. $Group['e'] = ($Mode &00010) ? 'x' : '-';
  651. $World['r'] = ($Mode &00004) ? 'r' : '-';
  652. $World['w'] = ($Mode &00002) ? 'w' : '-';
  653. $World['e'] = ($Mode &00001) ? 'x' : '-';
  654. // Adjuste pour SUID, SGID et sticky bit
  655. if ($Mode &0x800) $Owner['e'] = ($Owner['e'] == 'x') ? 's' : 'S';
  656. if ($Mode &0x400) $Group['e'] = ($Group['e'] == 'x') ? 's' : 'S';
  657. if ($Mode &0x200) $World['e'] = ($World['e'] == 'x') ? 't' : 'T';
  658. $Mode = $Type.$Owner['r'].$Owner['w'].$Owner['x'].' '.
  659. $Group['r'].$Group['w'].$Group['e'].' '.
  660. $World['r'].$World['w'].$World['e'];
  661. return $Mode.' ('.$theMode.') ';
  662. }
  663. /**
  664. * 获取可以上传的最大值
  665. * return * byte
  666. */
  667. function get_post_max(){
  668. $upload = ini_get('upload_max_filesize');
  669. $upload = $upload==''?ini_get('upload_max_size'):$upload;
  670. $post = ini_get('post_max_size');
  671. $upload = intval($upload)*1024*1024;
  672. $post = intval($post)*1024*1024;
  673. return $upload<$post?$upload:$post;
  674. }
  675. /**
  676. * 文件上传处理。单个文件上传,多个分多次请求
  677. * 调用demo
  678. * upload('file','D:/www/');
  679. */
  680. function upload($fileInput, $path = './'){
  681. global $config,$L;
  682. $file = $_FILES[$fileInput];
  683. if (!isset($file)) show_json($L['upload_error_null'],false);
  684. $file_name = iconv_system($file['name']);
  685. $save_path = get_filename_auto($path.$file_name);
  686. if(move_uploaded_file($file['tmp_name'],$save_path)){
  687. show_json($L['upload_success'],true,iconv_app($save_pathe));
  688. }else {
  689. show_json($L['move_error'],false);
  690. }
  691. }
  692. //分片上传处理
  693. function upload_chunk($fileInput, $path = './',$temp_path){
  694. global $config,$L;
  695. $file = $_FILES[$fileInput];
  696. $chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
  697. $chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 1;
  698. if (!isset($file)) show_json($L['upload_error_null'],false);
  699. $file_name = iconv_system($file['name']);
  700. if ($chunks>1) {//并发上传,不一定有前后顺序
  701. $temp_file_pre = $temp_path.md5($temp_path.$file_name).'.part';
  702. if (get_filesize($file['tmp_name']) ==0) {
  703. show_json($L['upload_success'],false,'chunk_'.$chunk.' error!');
  704. }
  705. if(move_uploaded_file($file['tmp_name'],$temp_file_pre.$chunk)){
  706. $done = true;
  707. for($index = 0; $index<$chunks; $index++ ){
  708. if (!file_exists($temp_file_pre.$index)) {
  709. $done = false;
  710. break;
  711. }
  712. }
  713. if (!$done){
  714. show_json($L['upload_success'],true,'chunk_'.$chunk.' success!');
  715. }
  716. $save_path = $path.$file_name;
  717. $out = fopen($save_path, "wb");
  718. if ($done && flock($out, LOCK_EX)) {
  719. for( $index = 0; $index < $chunks; $index++ ) {
  720. if (!$in = fopen($temp_file_pre.$index,"rb")) break;
  721. while ($buff = fread($in, 4096)) {
  722. fwrite($out, $buff);
  723. }
  724. fclose($in);
  725. unlink($temp_file_pre.$index);
  726. }
  727. flock($out, LOCK_UN);
  728. fclose($out);
  729. }
  730. show_json($L['upload_success'],true,iconv_app($save_path));
  731. }else {
  732. show_json($L['move_error'],false);
  733. }
  734. }
  735. //正常上传
  736. $save_path = get_filename_auto($path.$file_name); //自动重命名
  737. if(move_uploaded_file($file['tmp_name'],$save_path)){
  738. show_json($L['upload_success'],true,iconv_app($save_path));
  739. }else {
  740. show_json($L['move_error'],false);
  741. }
  742. }
  743. /**
  744. * 写日志
  745. * @param string $log 日志信息
  746. * @param string $type 日志类型 [system|app|...]
  747. * @param string $level 日志级别
  748. * @return boolean
  749. */
  750. function write_log($log, $type = 'default', $level = 'log'){
  751. $now_time = date('[y-m-d H:i:s]');
  752. $now_day = date('Y_m_d');
  753. // 根据类型设置日志目标位置
  754. $target = LOG_PATH . strtolower($type) . '/';
  755. mk_dir($target, 0777);
  756. if (! is_writable($target)) exit('path can not write!');
  757. switch($level){// 分级写日志
  758. case 'error': $target .= 'Error_' . $now_day . '.log';break;
  759. case 'warning': $target .= 'Warning_' . $now_day . '.log';break;
  760. case 'debug': $target .= 'Debug_' . $now_day . '.log';break;
  761. case 'info': $target .= 'Info_' . $now_day . '.log';break;
  762. case 'db': $target .= 'Db_' . $now_day . '.log';break;
  763. default: $target .= 'Log_' . $now_day . '.log';break;
  764. }
  765. //检测日志文件大小, 超过配置大小则重命名
  766. if (file_exists($target) && get_filesize($target) <= 100000) {
  767. $file_name = substr(basename($target),0,strrpos(basename($target),'.log')).'.log';
  768. rename($target, dirname($target) .'/'. $file_name);
  769. }
  770. clearstatcache();
  771. return error_log("$now_time $log\n", 3, $target);
  772. }