FileManager.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * upload文件管理
  5. *
  6. * @version 0.0.0
  7. * @author by huwhois
  8. * @time 2017/11/27
  9. */
  10. namespace app\sys\controller;
  11. use Exception;
  12. use UnexpectedValueException;
  13. use DirectoryIterator;
  14. use think\facade\View;
  15. use think\File;
  16. use think\Image;
  17. use think\facade\Config;
  18. use think\exception\ValidateException;
  19. use app\common\service\FileService;
  20. use app\common\model\FileManager as FileManagerModel;
  21. use think\file\UploadedFile;
  22. class FileManager extends Base
  23. {
  24. protected $modelName = 'FileManager';
  25. protected $t_suffix = '_thumb';
  26. protected $width = 400; // 缩略图高度
  27. protected $height = 300;
  28. protected $storage_path = 'public/storage';
  29. public function index()
  30. {
  31. $param = $this->request->param();
  32. $param['limit'] = isset($param['limit']) ? (int) $param['limit'] : Config::get('app.page_size');
  33. $list = FileManagerModel::queryPage($param);
  34. View::assign('list', $list);
  35. return View::fetch();
  36. }
  37. /**
  38. * 浏览文件
  39. */
  40. public function explorer()
  41. {
  42. $param = $this->request->param();
  43. $activepath = isset($param['activepath']) ? $param['activepath'] : '';
  44. $realpath = $this->app->getRootPath() . $this->storage_path . $activepath;
  45. try {
  46. $dirhandle = new DirectoryIterator($realpath);
  47. $dirs = $files = [];
  48. foreach ($dirhandle as $fileInfo) {
  49. if($fileInfo->isDot() || $fileInfo->getFilename() == '.gitignore') {
  50. continue;
  51. } elseif ($fileInfo->isDir()) {
  52. $dirs[] = $fileInfo->getFilename();
  53. } elseif ($fileInfo->isFile()) {
  54. $files[] = [
  55. 'filename' => $fileInfo->getFilename(),
  56. 'extension' => strtolower($fileInfo->getExtension()),
  57. 'size' => format_bytes($fileInfo->getSize()),
  58. 'time' => $fileInfo->getCTime(),
  59. ];
  60. }
  61. }
  62. $counts = count($dirs) + count($files);
  63. $activeurl = preg_replace("#[\/][^\/]*$#i", "", $activepath);
  64. View::assign([
  65. 'dirs' => $dirs,
  66. 'files' => $files,
  67. 'counts' => $counts,
  68. 'activeurl' => $activeurl,
  69. 'activepath' => $activepath,
  70. ]);
  71. return View::fetch();
  72. } catch(UnexpectedValueException $uve) {
  73. $this->error($uve->getMessage());
  74. }
  75. }
  76. /**
  77. * 附件上传
  78. */
  79. public function uploadFile()
  80. {
  81. $activepath = $this->request->has('activepath') ? $this->request->param('activepath') : '';
  82. $files = $this->request->file('upload_file');
  83. if ($files) {
  84. try {
  85. validate(
  86. [
  87. 'file' => [
  88. // 限制文件大小(单位b),这里限制为10M
  89. 'fileSize' => 10 * 1024 * 1024,
  90. // 限制文件后缀,多个后缀以英文逗号分割
  91. 'fileExt' => 'jpg,png,gif,jpeg,webp,jfif,pdf,doc,docx,xls,xlsx,ppt,pptx,txt'
  92. ]
  93. ],
  94. [
  95. 'file.fileSize' => '文件太大',
  96. 'file.fileExt' => '不支持的文件后缀',
  97. ]
  98. )->check(['file' => $files]);
  99. $savenames = [];
  100. $uploadFiles = [];
  101. if (!is_array($files) && $files instanceof UploadedFile) {
  102. $uploadFiles[] = $files;
  103. } else {
  104. $uploadFiles = $files;
  105. }
  106. $url = Config::get('filesystem.disks.public.url');
  107. foreach ($uploadFiles as $file) {
  108. $fileinfo = new FileManagerModel();
  109. $fileinfo->title = $file->getOriginalName();
  110. $fileinfo->filesize = $file->getSize();
  111. $fileinfo->filetime = $file->getCTime();
  112. $fileinfo->fileextension = $file->extension();
  113. $fileinfo->username = $this->getSysUser()->username;
  114. $fileinfo->hash_md5 = $file->md5();
  115. if (empty($activepath)) {
  116. $savename = \think\facade\Filesystem::disk('public')->putFile('/', $file);
  117. $fileinfo->filepath = $url . '/' . $savename;
  118. $fileinfo->filename = basename($savename);
  119. } else {
  120. $savename = $activepath . '/' . $file->hashName();
  121. $savepath = $this->app->getRootPath() . $this->storage_path . $savename;
  122. $file = $file->move($this->app->getRootPath() . $this->storage_path . $activepath, $savepath);
  123. $fileinfo->filepath = $url . $savename;
  124. $fileinfo->filename = $file->hashName();
  125. }
  126. $fileinfo->save();
  127. $savenames[] = $fileinfo->filepath;
  128. }
  129. return json(['code' => 0, 'msg'=>'上传成功', 'filename'=>$savenames]);
  130. } catch (ValidateException $e) {
  131. $this->error($e->getMessage());
  132. }
  133. } else {
  134. $this->error('图片不能为空');
  135. }
  136. }
  137. /**
  138. * 修改文件title
  139. */
  140. public function updateFileTitle($id = 0, $filetitle = '')
  141. {
  142. $fileInfo = FileManagerModel::find($id);
  143. if ($fileInfo == null) {
  144. return json(['code'=>1, 'fileid='.$id.'不存在']);
  145. }
  146. $fileInfo->title = $filetitle;
  147. if ($fileInfo->save()) {
  148. return json(['code'=>0, 'msg'=>'success']);
  149. } else {
  150. return json(['code'=>1, 'msg'=>'failed']);
  151. }
  152. }
  153. /**
  154. * 删除
  155. * @param int|array $id info id
  156. * @return array
  157. */
  158. public function delete($id)
  159. {
  160. if ($this->request->isPost()) {
  161. $whereOp = '=';
  162. if (is_array($id)) {
  163. $whereOp = 'IN';
  164. }
  165. $list = FileManagerModel::where('fileid', $whereOp, $id)->select();
  166. foreach ($list as $value) {
  167. $file = $this->app->getRootPath() . 'public' . $value->filepath;
  168. if (file_exists($file)) {
  169. unlink($file);
  170. }
  171. }
  172. if (FileManagerModel::destroy($id)) {
  173. return ['code' => 0,'msg'=>'删除成功'];
  174. } else {
  175. return ['code' => 1,'msg'=>'删除失败'];
  176. }
  177. }
  178. }
  179. /**
  180. * 删除空目录
  181. */
  182. public function deldir()
  183. {
  184. if ($this->request->isPost()) {
  185. $dir = str_replace('/', DIRECTORY_SEPARATOR, $this->request->param('dir'));
  186. $dir_name = $this->app->getRootPath() . $this->storage_path . DIRECTORY_SEPARATOR . $dir;
  187. try {
  188. rmdir($dir_name);
  189. return ['code' => 0, 'msg' => 'success'];
  190. } catch (Exception $e) {
  191. return ['code' => 1, 'msg' => 'failed, 目录不为空'];
  192. }
  193. }
  194. }
  195. /**
  196. * 删除文件
  197. */
  198. public function delfile()
  199. {
  200. if ($this->request->isPost()) {
  201. $filename = str_replace('/', DIRECTORY_SEPARATOR, $this->request->param('filename'));
  202. $filepath = $this->app->getRootPath() . $this->storage_path . DIRECTORY_SEPARATOR . $filename;
  203. if (unlink($filepath)) {
  204. return ['code' => 0, 'msg' => 'success'];
  205. } else {
  206. return ['code' => 1, 'msg' => 'failed'];
  207. }
  208. }
  209. }
  210. /**
  211. * 处理上传的图片
  212. */
  213. protected function dealUploadImg(File $file, $water, $thumb, $width, $height, $overwrite)
  214. {
  215. $savename = "";
  216. $thumbname = "";
  217. if ($water == true || $thumb == true) {
  218. $image = Image::open($file);
  219. if ($water) {
  220. $type = $this->system->water_type ?: Config::get('filesystem.water.type');
  221. if ($type == 'water') {
  222. $watemark = $this->system->watermark ?: Config::get('filesystem.water.watermark');
  223. $image->water($watemark);
  224. } else {
  225. $watetext = $this->system->watertext ?: Config::get('filesystem.water.watertext');
  226. $image->text($watetext, Config::get('filesystem.water.waterfont'), 30, '#ffffff30');
  227. }
  228. }
  229. $savename = $file->hashName();
  230. $realPath = Config::get('filesystem.disks.public.root') . '/' . $savename;
  231. if ($thumb == true) {
  232. if ($overwrite == true) {
  233. $image->thumb($width, $height, 1);
  234. $image->save($realPath);
  235. } else {
  236. $image->save($realPath);
  237. $image->thumb($width, $height, 1);
  238. $ext = $file->extension();
  239. $thumbname = str_replace('.' . $ext, '', str_replace('\\', '/', $savename)) . $this->t_suffix . '.' . $ext;
  240. $image->save(Config::get('filesystem.disks.public.root') . '/' . $thumbname);
  241. }
  242. } else {
  243. $image->save($realPath);
  244. }
  245. unset($image);
  246. } else {
  247. $savename = \think\facade\Filesystem::disk('public')->putFile('/', $file);
  248. }
  249. return [
  250. 'picname' => str_replace('\\', '/', $savename),
  251. 'thumbname' => $thumbname
  252. ];
  253. }
  254. /**
  255. * 图片上传(iframe 页面)
  256. */
  257. public function uploadimg(string $img_id = 'picture', $water = false, $thumb = false, $width = 400, $height = 300, $overwrite = false)
  258. {
  259. View::assign([
  260. 'img_id' => $img_id,
  261. 'water' => $water,
  262. 'thumb' => $thumb,
  263. 'width' => $width,
  264. 'height' => $height,
  265. 'overwrite' => $overwrite
  266. ]);
  267. return View::fetch();
  268. }
  269. /**
  270. * 本地图片上传
  271. * @file upload_file 上传的文件
  272. * @param string $img_id 图片ipnut text id 默认值 picture
  273. * @param boolean $water 是否添加水印
  274. * @param boolean $thumb 是否制作缩略图
  275. * @param int $width 缩略图最大宽
  276. * @param int $height 缩略图最大高
  277. * @param bool $overwrite 生成缩略图后是否保存原图
  278. */
  279. public function uploadLocalImg(string $img_id = 'picture', $water = false, $thumb = false, $width = 400, $height = 300, $overwrite = false)
  280. {
  281. if ($this->request->isPost()) {
  282. $file = $this->request->file('upload_file');
  283. if ($file) {
  284. try {
  285. validate(
  286. [
  287. 'file' => [
  288. // 限制文件大小(单位b),这里限制为4M
  289. 'fileSize' => 4 * 1024 * 1024,
  290. // 限制文件后缀,多个后缀以英文逗号分割
  291. 'fileExt' => 'jpg,png,gif,jpeg,webp,jfif'
  292. ]
  293. ],
  294. [
  295. 'file.fileSize' => '文件太大',
  296. 'file.fileExt' => '不支持的文件后缀',
  297. ]
  298. )->check(['file' => $file]);
  299. $arr = $this->dealUploadImg($file, $water, $thumb, $width, $height, $overwrite);
  300. return array_merge(
  301. [
  302. 'code' => 0,
  303. 'img_id' => $img_id,
  304. 'picture_url' => Config::get('filesystem.disks.public.url') . '/'
  305. ],
  306. $arr
  307. );
  308. } catch (ValidateException $e) {
  309. $this->error($e->getMessage());
  310. }
  311. } else {
  312. $this->error('图片不能为空');
  313. }
  314. }
  315. }
  316. /**
  317. * 网络图片上传
  318. * @paran string url_file 网络图片地址
  319. * @param string $img_id 图片ipnut text id 默认值 picture
  320. * @param boolean $water 是否添加水印
  321. * @param boolean $thumb 是否制作缩略图
  322. * @param int $width 缩略图最大宽
  323. * @param int $height 缩略图最大高
  324. * @param bool $overwrite 生成缩略图后是否保存原图
  325. */
  326. public function uploadUrlImg(string $img_id = 'picture', $water = false, $thumb = false, $width = 400, $height = 300, $overwrite = false)
  327. {
  328. if ($this->request->isPost()) {
  329. $urlImg = $this->request->param('url_file');
  330. if ($urlImg) {
  331. try {
  332. $fileService = new FileService();
  333. $file = $fileService->downloadUrlImg($urlImg);
  334. $arr = $this->dealUploadImg($file, $water, $thumb, $width, $height, $overwrite);
  335. @unlink($file->realPath);
  336. return array_merge(
  337. [
  338. 'code' => 0,
  339. 'img_id' => $img_id,
  340. 'picture_url' => Config::get('filesystem.disks.public.url') . '/'
  341. ],
  342. $arr
  343. );
  344. } catch (\think\exception\ValidateException $e) {
  345. $this->error($e->getMessage());
  346. }
  347. } else {
  348. $this->error('图片地址不能为空');
  349. }
  350. }
  351. }
  352. /**
  353. * 选择服务器图片
  354. * @paran string online_file 服务器图片地址
  355. * @param string $img_id 图片ipnut text id 默认值 picture
  356. * @param boolean $water 是否添加水印
  357. * @param boolean $thumb 是否制作缩略图
  358. * @param int $width 缩略图最大宽
  359. * @param int $height 缩略图最大高
  360. * @param bool $overwrite 生成缩略图后是否保存原图
  361. */
  362. public function uploadonlineimg(string $img_id = 'picture', $water = false, $thumb = false, $width = 400, $height = 300, $overwrite = false)
  363. {
  364. if ($this->request->isPost()) {
  365. $pathImg = $this->request->param('online_file');
  366. if ($pathImg && file_exists($this->app->getRootPath() . "public" . $pathImg)) {
  367. $picname = $pathImg;
  368. $thumbname = "";
  369. if ($thumb) {
  370. if (stripos($picname, $this->t_suffix)) {
  371. $thumbname = $pathImg;
  372. } else {
  373. try {
  374. $file = new File($this->app->getRootPath() . "public" . $pathImg);
  375. $ext = $file->getExtension();
  376. $thumbname = str_replace('.' . $ext, '', str_replace('\\', '/', $picname)) . $this->t_suffix . '.' . $ext;
  377. if (!file_exists($thumbname)) {
  378. $image = Image::open($file);
  379. $image->thumb($width, $height, 1);
  380. $image->save($this->app->getRootPath() . "public" . $thumbname);
  381. unset($image);
  382. }
  383. if ($overwrite) {
  384. $picname = $thumbname;
  385. }
  386. } catch (Exception $e) {
  387. $this->error($e->getMessage());
  388. }
  389. }
  390. }
  391. return [
  392. 'code' => 0,
  393. 'img_id' => $img_id,
  394. 'picname' => $picname,
  395. 'thumbname' => $thumbname,
  396. ];
  397. } else {
  398. $this->error('图片地址不存在');
  399. }
  400. }
  401. }
  402. public function onlineimg($page)
  403. {
  404. $files = FileService::getFiles(Config::get('filesystem.disks.public.root'));
  405. if (!count($files)) {
  406. return json_encode(array(
  407. "state" => "no match file",
  408. "list" => array(),
  409. "start" => $page,
  410. "total" => count($files)
  411. ));
  412. }
  413. /* 获取指定范围的列表 */
  414. $page = $page - 1 < 0 ? 0 : (int)$page - 1;
  415. $size = 20;
  416. $start = $page * $size;
  417. $end = $start + $size;
  418. $len = count($files);
  419. for ($i = min($end, $len) - 1, $list = array(); $i < $len && $i >= 0 && $i >= $start; $i--) {
  420. $list[] = $files[$i];
  421. }
  422. return json([
  423. "code" => 0,
  424. "list" => $list,
  425. "page" => $page + 1,
  426. "total" => count($files)
  427. ]);
  428. }
  429. /**
  430. * 判断(远程)文件是否为图片
  431. */
  432. // public function isImg()
  433. // {
  434. // if ($this->request->isAjax()) {
  435. // $filename = $this->request->param('filename');
  436. // $res = \mylib\GetImageByurl::isImg($filename);
  437. // if (!$res) {
  438. // $this->error('该图片不合法');
  439. // } else {
  440. // return ['code'=>2,'msg'=>'图片地址可用'];
  441. // }
  442. // }
  443. // }
  444. /**
  445. * ckeditor 富文本编辑器上传图片
  446. */
  447. public function ckeditorUploadImage()
  448. {
  449. if ($this->request->isPost()) {
  450. $file = $this->request->file('upload');
  451. if ($file) {
  452. try {
  453. validate(
  454. [
  455. 'file' => [
  456. // 限制文件大小(单位b),这里限制为4M
  457. 'fileSize' => 4 * 1024 * 1024,
  458. // 限制文件后缀,多个后缀以英文逗号分割
  459. 'fileExt' => 'jpg,png,gif,jpeg,webp,jfif'
  460. ]
  461. ],
  462. [
  463. 'file.fileSize' => '文件太大',
  464. 'file.fileExt' => '不支持的文件后缀',
  465. ]
  466. )->check(['file' => $file]);
  467. $savename = \think\facade\Filesystem::disk('public')->putFile('/', $file);
  468. return json([
  469. 'uploaded' => 1,
  470. 'fileName' => basename($savename),
  471. 'url' => Config::get('filesystem.disks.public.url') . '/' . $savename
  472. ]);
  473. } catch (\think\exception\ValidateException $e) {
  474. $this->error($e->getMessage());
  475. return json([
  476. 'uploaded' => 1,
  477. 'error' => ['message' => $e->getMessage()]
  478. ]);
  479. }
  480. } else {
  481. return json([
  482. 'uploaded' => 1,
  483. 'error' => ['message' => '图片不能为空']
  484. ]);
  485. }
  486. }
  487. }
  488. }